growthbook 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,57 @@
1
+ require 'growthbook'
2
+ require 'json'
3
+
4
+ describe 'client' do
5
+ describe ".enabled" do
6
+ it "chooses variation -1 when client is disabled" do
7
+ client = Growthbook::Client.new(enabled: false)
8
+ user = client.user(id: "1")
9
+ experiment = Growthbook::Experiment.new("my-test", 2)
10
+ expect(user.experiment(experiment).variation).to eq(-1)
11
+ end
12
+ end
13
+ describe ".importExperimentsHash" do
14
+ it("imports correctly") do
15
+ client = Growthbook::Client.new
16
+
17
+ # Example JSON response from the GrowthBook API
18
+ json = '{
19
+ "status": 200,
20
+ "experiments": {
21
+ "my-test": {
22
+ "variations": 2,
23
+ "coverage": 0.6,
24
+ "weights": [0.8, 0.2],
25
+ "anon": true,
26
+ "force": 1,
27
+ "targeting": [
28
+ "source = google"
29
+ ],
30
+ "data": {
31
+ "color": ["blue", "green"]
32
+ }
33
+ },
34
+ "my-stopped-test": {
35
+ "variations": 3,
36
+ "force": 1
37
+ }
38
+ }
39
+ }'
40
+
41
+ parsed = JSON.parse(json)
42
+ client.importExperimentsHash(parsed["experiments"])
43
+
44
+ expect(client.experiments.length).to eq(2)
45
+
46
+ experiment = client.experiments[0]
47
+ expect(experiment.id).to eq("my-test")
48
+ expect(experiment.variations).to eq(2)
49
+ expect(experiment.coverage).to eq(0.6)
50
+ expect(experiment.weights[0]).to eq(0.8)
51
+ expect(experiment.anon).to eq(true)
52
+ expect(experiment.force).to eq(1)
53
+ expect(experiment.targeting[0]).to eq("source = google")
54
+ expect(experiment.data["color"][0]).to eq("blue")
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,120 @@
1
+ require 'growthbook'
2
+ require 'json'
3
+
4
+ describe 'context' do
5
+ describe "feature helper methods" do
6
+ gb = Growthbook::Context.new(
7
+ features: {
8
+ feature1: {
9
+ defaultValue: 1
10
+ },
11
+ feature2: {
12
+ defaultValue: 0
13
+ }
14
+ }
15
+ )
16
+
17
+ it ".on?" do
18
+ expect(gb.on?(:feature1)).to eq(true)
19
+ expect(gb.on?(:feature2)).to eq(false)
20
+ end
21
+ it ".off?" do
22
+ expect(gb.off?(:feature1)).to eq(false)
23
+ expect(gb.off?(:feature2)).to eq(true)
24
+ end
25
+ it ".feature_value" do
26
+ expect(gb.feature_value(:feature1)).to eq(1)
27
+ expect(gb.feature_value(:feature2)).to eq(0)
28
+ end
29
+ end
30
+
31
+ describe "forced feature values" do
32
+ it "uses forced values" do
33
+ gb = Growthbook::Context.new(
34
+ features: {
35
+ feature: {
36
+ defaultValue: "a"
37
+ },
38
+ feature2: {
39
+ defaultValue: true
40
+ }
41
+ }
42
+ )
43
+
44
+ gb.forced_features = {
45
+ feature: "b",
46
+ another: 2
47
+ }
48
+
49
+ expect(gb.feature_value(:feature)).to eq("b")
50
+ expect(gb.feature_value(:feature2)).to eq(true)
51
+ expect(gb.feature_value(:another)).to eq(2)
52
+ expect(gb.feature_value(:unknown)).to eq(nil)
53
+ end
54
+ end
55
+
56
+ describe "tracking" do
57
+ it "queues up impressions" do
58
+ class MyImpressionListener
59
+ attr_accessor :tracked
60
+ def on_experiment_viewed(exp, res)
61
+ @tracked = [exp.to_json, res.to_json]
62
+ end
63
+ end
64
+
65
+ listener = MyImpressionListener.new
66
+
67
+ gb = Growthbook::Context.new(
68
+ attributes: {
69
+ id: "123"
70
+ },
71
+ features: {
72
+ feature1: {
73
+ defaultValue: 1,
74
+ rules: [
75
+ {
76
+ variations: [2, 3]
77
+ }
78
+ ]
79
+ },
80
+ feature2: {
81
+ defaultValue: 0,
82
+ rules: [
83
+ {
84
+ variations: [4, 5]
85
+ }
86
+ ]
87
+ }
88
+ },
89
+ listener: listener
90
+ )
91
+
92
+ expect(gb.impressions).to eq({})
93
+ expect(listener.tracked).to eq(nil)
94
+
95
+ gb.on? :feature1
96
+
97
+ expect(gb.impressions["feature1"].to_json).to eq({
98
+ "hashAttribute" => "id",
99
+ "hashValue" => "123",
100
+ "inExperiment" => true,
101
+ "value" => 2,
102
+ "variationId" => 0,
103
+ })
104
+
105
+ expect(listener.tracked).to eq([
106
+ {
107
+ "key" => "feature1",
108
+ "variations" => [2, 3]
109
+ },
110
+ {
111
+ "hashAttribute" => "id",
112
+ "hashValue" => "123",
113
+ "inExperiment" => true,
114
+ "value" => 2,
115
+ "variationId" => 0,
116
+ }
117
+ ])
118
+ end
119
+ end
120
+ end
data/spec/json_spec.rb ADDED
@@ -0,0 +1,159 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'growthbook'
4
+ require 'json'
5
+
6
+ file = File.read(File.join(File.dirname(__FILE__), 'cases.json'))
7
+ test_cases = JSON.parse(file)
8
+
9
+ def roundArray(arr)
10
+ arr.map do |v|
11
+ v.is_a?(Float) || v.is_a?(Integer) ? v.round(5) : roundArray(v)
12
+ end
13
+ end
14
+
15
+ describe 'test suite' do
16
+ describe 'hash' do
17
+ test_cases['hash'].each do |test_case|
18
+ value, expected = test_case
19
+
20
+ it value do
21
+ result = Growthbook::Util.hash(value)
22
+ expect(result.round(5)).to eq expected.round(5)
23
+ end
24
+ end
25
+ end
26
+
27
+ describe 'getBucketRanges' do
28
+ # Loop through each test case in the JSON file
29
+ test_cases['getBucketRange'].each do |test_case|
30
+ # Extract data about the test case
31
+ test_name, args, expected = test_case
32
+ num_variations, coverage, weights = args
33
+
34
+ # Run the actual test case
35
+ it test_name do
36
+ result = Growthbook::Util.get_bucket_ranges(
37
+ num_variations,
38
+ coverage,
39
+ weights
40
+ )
41
+
42
+ expect(roundArray(result)).to eq(roundArray(expected))
43
+ end
44
+ end
45
+ end
46
+
47
+ describe 'chooseVariation' do
48
+ # Loop through each test case in the JSON file
49
+ test_cases['chooseVariation'].each do |test_case|
50
+ # Extract data about the test case
51
+ test_name, n, ranges, expected = test_case
52
+
53
+ # Run the actual test case
54
+ it test_name do
55
+ result = Growthbook::Util.choose_variation(n, ranges)
56
+ expect(result).to eq(expected)
57
+ end
58
+ end
59
+ end
60
+
61
+ describe 'getQueryStringOverride' do
62
+ # Loop through each test case in the JSON file
63
+ test_cases['getQueryStringOverride'].each do |test_case|
64
+ # Extract data about the test case
65
+ test_name, key, url, num_variations, expected = test_case
66
+
67
+ # Run the actual test case
68
+ it test_name do
69
+ result = Growthbook::Util.get_query_string_override(
70
+ key,
71
+ url,
72
+ num_variations
73
+ )
74
+ expect(result).to eq(expected)
75
+ end
76
+ end
77
+ end
78
+
79
+ describe 'inNamespace' do
80
+ # Loop through each test case in the JSON file
81
+ test_cases['inNamespace'].each do |test_case|
82
+ # Extract data about the test case
83
+ test_name, id, namespace, expected = test_case
84
+
85
+ # Run the actual test case
86
+ it test_name do
87
+ result = Growthbook::Util.in_namespace(
88
+ id,
89
+ namespace
90
+ )
91
+ expect(result).to eq(expected)
92
+ end
93
+ end
94
+ end
95
+
96
+ describe 'getEqualWeights' do
97
+ # Loop through each test case in the JSON file
98
+ test_cases['getEqualWeights'].each do |test_case|
99
+ # Extract data about the test case
100
+ num_variations, expected = test_case
101
+
102
+ # Run the actual test case
103
+ it num_variations.to_s do
104
+ result = Growthbook::Util.get_equal_weights(
105
+ num_variations
106
+ )
107
+ expect(roundArray(result)).to eq(roundArray(expected))
108
+ end
109
+ end
110
+ end
111
+
112
+ describe 'evalCondition' do
113
+ # Loop through each test case in the JSON file
114
+ test_cases['evalCondition'].each do |test_case|
115
+ # Extract data about the test case
116
+ test_name, condition, attributes, expected = test_case
117
+
118
+ # Run the actual test case
119
+ it test_name do
120
+ result = Growthbook::Conditions.eval_condition(
121
+ attributes,
122
+ condition
123
+ )
124
+ expect(result).to eq(expected)
125
+ end
126
+ end
127
+ end
128
+ describe 'feature' do
129
+ # Loop through each test case in the JSON file
130
+ test_cases['feature'].each do |test_case|
131
+ # Extract data about the test case
132
+ test_name, context, key, expected = test_case
133
+
134
+ # Run the actual test case
135
+ it test_name do
136
+ gb = Growthbook::Context.new(context)
137
+ result = gb.eval_feature(key)
138
+ expect(result.to_json).to eq(expected)
139
+ end
140
+ end
141
+ end
142
+
143
+ describe 'run' do
144
+ # Loop through each test case in the JSON file
145
+ test_cases['run'].each do |test_case|
146
+ # Extract data about the test case
147
+ test_name, context, experiment, value, in_experiment = test_case
148
+
149
+ # Run the actual test case
150
+ it test_name do
151
+ gb = Growthbook::Context.new(context)
152
+ exp = Growthbook::InlineExperiment.new(experiment)
153
+ result = gb.run(exp)
154
+ expect(result.value).to eq(value)
155
+ expect(result.in_experiment).to eq(in_experiment)
156
+ end
157
+ end
158
+ end
159
+ end
data/spec/user_spec.rb ADDED
@@ -0,0 +1,213 @@
1
+ require 'growthbook'
2
+
3
+ describe 'user' do
4
+ describe ".experiment" do
5
+ it "uses experiment overrides in client first" do
6
+ client = Growthbook::Client.new
7
+ override = Growthbook::Experiment.new("my-test", 2)
8
+ client.experiments << override
9
+
10
+ experiment = Growthbook::Experiment.new("my-test", 2)
11
+ user = client.user(id: "1")
12
+ result = user.experiment(experiment)
13
+
14
+ expect(result.experiment).to eq(override)
15
+ end
16
+
17
+ it "assigns properly with both user id and anonymous ids" do
18
+ client = Growthbook::Client.new
19
+ userOnly = client.user(id: "1")
20
+ anonOnly = client.user(anonId: "2")
21
+ both = client.user(id: "1", anonId: "2")
22
+
23
+ experimentAnon = Growthbook::Experiment.new("my-test", 2, anon:true)
24
+ experimentUser = Growthbook::Experiment.new("my-test", 2, anon:false)
25
+
26
+ expect(userOnly.experiment(experimentUser).variation).to eq(1)
27
+ expect(both.experiment(experimentUser).variation).to eq(1)
28
+ expect(anonOnly.experiment(experimentUser).variation).to eq(-1)
29
+
30
+ expect(userOnly.experiment(experimentAnon).variation).to eq(-1)
31
+ expect(both.experiment(experimentAnon).variation).to eq(0)
32
+ expect(anonOnly.experiment(experimentAnon).variation).to eq(0)
33
+ end
34
+
35
+ it "returns variation config data" do
36
+ client = Growthbook::Client.new
37
+ user = client.user(id: "1")
38
+ experiment = Growthbook::Experiment.new("my-test", 2, data: {
39
+ :color => ["blue", "green"],
40
+ :size => ["small", "large"]
41
+ })
42
+
43
+ # Get correct config data
44
+ result = user.experiment(experiment)
45
+ expect(result.data[:color]).to eq("green")
46
+ expect(result.data[:size]).to eq("large")
47
+
48
+ # Fallback to control config data if not in test
49
+ experiment.coverage = 0.01
50
+ result = user.experiment(experiment)
51
+ expect(result.data[:color]).to eq("blue")
52
+ expect(result.data[:size]).to eq("small")
53
+
54
+ # Null for undefined keys
55
+ expect(result.data[:unknown]).to eq(nil)
56
+ end
57
+
58
+ it "uses forced variations properly" do
59
+ client = Growthbook::Client.new
60
+ experiment = Growthbook::Experiment.new("my-test", 2, force: -1)
61
+ user = client.user(id: "1")
62
+
63
+ expect(user.experiment(experiment).variation).to eq(-1)
64
+ experiment.force = 0
65
+ expect(user.experiment(experiment).variation).to eq(0)
66
+ experiment.force = 1
67
+ expect(user.experiment(experiment).variation).to eq(1)
68
+ end
69
+
70
+ it "evaluates targeting before forced variation" do
71
+ client = Growthbook::Client.new
72
+ experiment = Growthbook::Experiment.new("my-test", 2, force: 1, targeting: ["age > 18"])
73
+ user = client.user(id: "1")
74
+
75
+ expect(user.experiment(experiment).variation).to eq(-1)
76
+ end
77
+
78
+ it "sets the shouldTrack flag on results" do
79
+ client = Growthbook::Client.new
80
+ experiment = Growthbook::Experiment.new("my-test", 2, data: {"color" => ["blue", "green"]})
81
+ client.experiments << experiment
82
+ user = client.user(id: "1")
83
+
84
+ # Normal
85
+ expect(user.experiment("my-test").shouldTrack?).to eq(true)
86
+ expect(user.experiment("my-test").forced?).to eq(false)
87
+ expect(user.lookupByDataKey("color").shouldTrack?).to eq(true)
88
+ expect(user.lookupByDataKey("color").forced?).to eq(false)
89
+
90
+ # Failed coverage
91
+ experiment.coverage = 0.01
92
+ expect(user.experiment("my-test").shouldTrack?).to eq(false)
93
+ expect(user.experiment("my-test").forced?).to eq(false)
94
+ expect(user.lookupByDataKey("color")).to eq(nil)
95
+
96
+ # Forced variation
97
+ experiment.coverage = 1.0
98
+ experiment.force = 1
99
+ expect(user.experiment("my-test").shouldTrack?).to eq(false)
100
+ expect(user.experiment("my-test").forced?).to eq(true)
101
+ expect(user.lookupByDataKey("color").shouldTrack?).to eq(false)
102
+ expect(user.lookupByDataKey("color").forced?).to eq(true)
103
+ end
104
+
105
+ it "can target an experiment given rules and attributes" do
106
+ client = Growthbook::Client.new
107
+ experiment = Growthbook::Experiment.new("my-test", 2, targeting: [
108
+ "member = true",
109
+ "age > 18",
110
+ "source ~ (google|yahoo)",
111
+ "name != matt",
112
+ "email !~ ^.*@exclude.com$"
113
+ ])
114
+
115
+ attributes = {
116
+ :member => true,
117
+ :age => 21,
118
+ :source => 'yahoo',
119
+ :name => 'george',
120
+ :email => 'test@example.com'
121
+ }
122
+
123
+ # Matches all
124
+ user = client.user(id: "1", attributes: attributes)
125
+ expect(user.experiment(experiment).variation).to eq(1)
126
+
127
+ # Missing negative checks
128
+ user.attributes={
129
+ :member => true,
130
+ :age => 21,
131
+ :source => "yahoo"
132
+ }
133
+ expect(user.experiment(experiment).variation).to eq(1)
134
+
135
+ # Fails boolean
136
+ user.attributes=attributes.merge({
137
+ :member => false
138
+ })
139
+ expect(user.experiment(experiment).variation).to eq(-1)
140
+ end
141
+ end
142
+
143
+ describe "resultsToTrack" do
144
+ it "queues up results" do
145
+ client = Growthbook::Client.new
146
+ user = client.user(id: "1")
147
+
148
+ user.experiment(Growthbook::Experiment.new("my-test", 2))
149
+ user.experiment(Growthbook::Experiment.new("my-test2", 2))
150
+ user.experiment(Growthbook::Experiment.new("my-test3", 2))
151
+
152
+ expect(user.resultsToTrack.length).to eq(3)
153
+ end
154
+ it "ignores duplicates" do
155
+ client = Growthbook::Client.new
156
+ user = client.user(id: "1")
157
+ user.experiment(Growthbook::Experiment.new("my-test", 2))
158
+ user.experiment(Growthbook::Experiment.new("my-test", 2))
159
+
160
+ expect(user.resultsToTrack.length).to eq(1)
161
+ end
162
+ end
163
+
164
+ describe ".lookupByDataKey" do
165
+ before(:all) do
166
+ @client = Growthbook::Client.new
167
+ @client.experiments << Growthbook::Experiment.new(
168
+ "button-color-size-chrome",
169
+ 2,
170
+ :targeting => ["browser = chrome"],
171
+ :data => {
172
+ "button.color" => ["blue", "green"],
173
+ "button.size" => ["small", "large"]
174
+ }
175
+ )
176
+ @client.experiments << Growthbook::Experiment.new(
177
+ "button-color-safari",
178
+ 2,
179
+ :targeting => ["browser = safari"],
180
+ :data => {
181
+ "button.color" => ["blue", "green"]
182
+ }
183
+ )
184
+ end
185
+ it "returns nil when there are no matches" do
186
+ user = @client.user(id: "1")
187
+
188
+ # No matches
189
+ expect(user.lookupByDataKey("button.unknown")).to eq(nil)
190
+ end
191
+ it "returns the first matching experiment" do
192
+ user = @client.user(id: "1", attributes: {:browser => "chrome"})
193
+
194
+ color = user.lookupByDataKey("button.color")
195
+ expect(color.value).to eq("blue")
196
+ expect(color.experiment.id).to eq("button-color-size-chrome")
197
+
198
+ size = user.lookupByDataKey("button.size")
199
+ expect(size.value).to eq("small")
200
+ expect(size.experiment.id).to eq("button-color-size-chrome")
201
+ end
202
+ it "skips experiments that fail targeting rules" do
203
+ user = @client.user(id: "1", attributes: {:browser => "safari"})
204
+
205
+ color = user.lookupByDataKey("button.color")
206
+ expect(color.value).to eq("blue")
207
+ expect(color.experiment.id).to eq("button-color-safari")
208
+
209
+ size = user.lookupByDataKey("button.size")
210
+ expect(size).to eq(nil)
211
+ end
212
+ end
213
+ end
data/spec/util_spec.rb ADDED
@@ -0,0 +1,154 @@
1
+ require 'growthbook'
2
+
3
+ describe 'util' do
4
+ describe "checkRule function" do
5
+ it "works for all operators and normal inputs" do
6
+ # =
7
+ expect(Growthbook::Util.checkRule("test", "=", "test")).to eq(true)
8
+ expect(Growthbook::Util.checkRule("test", "=", "other")).to eq(false)
9
+ # !=
10
+ expect(Growthbook::Util.checkRule("test", "!=", "other")).to eq(true)
11
+ expect(Growthbook::Util.checkRule("test", "!=", "test")).to eq(false)
12
+ # >
13
+ expect(Growthbook::Util.checkRule("b", ">", "a")).to eq(true)
14
+ expect(Growthbook::Util.checkRule("a", ">", "b")).to eq(false)
15
+ # <
16
+ expect(Growthbook::Util.checkRule("a", "<", "b")).to eq(true)
17
+ expect(Growthbook::Util.checkRule("b", "<", "a")).to eq(false)
18
+ # ~
19
+ expect(Growthbook::Util.checkRule("123-456-abc", "~", "^[0-9]{3}-[0-9]{3}-[a-z]{3}$")).to eq(true)
20
+ expect(Growthbook::Util.checkRule("123-abc-456", "~", "^[0-9]{3}-[0-9]{3}-[a-z]{3}$")).to eq(false)
21
+ # !~
22
+ expect(Growthbook::Util.checkRule("123-abc-456", "!~", "^[0-9]{3}-[0-9]{3}-[a-z]{3}$")).to eq(true)
23
+ expect(Growthbook::Util.checkRule("123-456-abc", "!~", "^[0-9]{3}-[0-9]{3}-[a-z]{3}$")).to eq(false)
24
+ end
25
+
26
+ it "returns true when there's an unknown operator" do
27
+ expect(Growthbook::Util.checkRule("abc", "*", "123")).to eq(true)
28
+ end
29
+
30
+ it "returns false when the regex is invalid" do
31
+ expect(Growthbook::Util.checkRule("abc", "~", "abc)")).to eq(false)
32
+ end
33
+
34
+ it "compares numeric strings with natural ordering" do
35
+ expect(Growthbook::Util.checkRule("10", ">", "9")).to eq(true)
36
+ expect(Growthbook::Util.checkRule("9", "<", "1000")).to eq(true)
37
+ expect(Growthbook::Util.checkRule("90", ">", "800")).to eq(false)
38
+ expect(Growthbook::Util.checkRule("-10", "<", "10")).to eq(true)
39
+ expect(Growthbook::Util.checkRule("10", ">", "abc")).to eq(false)
40
+ end
41
+
42
+ it "checks for numeric equality properly" do
43
+ expect(Growthbook::Util.checkRule("9.0", "=", "9")).to eq(true)
44
+ expect(Growthbook::Util.checkRule("1.3", "!=", "1.30000")).to eq(false)
45
+ end
46
+
47
+ it "handles empty strings" do
48
+ expect(Growthbook::Util.checkRule("", "=", "")).to eq(true)
49
+ expect(Growthbook::Util.checkRule("", "!=", "")).to eq(false)
50
+ expect(Growthbook::Util.checkRule("", ">", "")).to eq(false)
51
+ expect(Growthbook::Util.checkRule("", "<", "")).to eq(false)
52
+ expect(Growthbook::Util.checkRule("", "~", "")).to eq(true)
53
+ expect(Growthbook::Util.checkRule("", "!~", "")).to eq(false)
54
+ end
55
+ end
56
+
57
+ describe "chooseVariation function" do
58
+ it "does not have a sample ratio mismatch bug" do
59
+ # Full coverage
60
+ experiment = Growthbook::Experiment.new("my-test", 2)
61
+ variations = [0, 0]
62
+ for i in 0..999
63
+ variations[Growthbook::Util.chooseVariation(i.to_s, experiment)] += 1
64
+ end
65
+ expect(variations[0]).to eq(503)
66
+ end
67
+
68
+ it "does not have a sample ratio mismatch bug for reduced coverage" do
69
+ # Reduced coverage
70
+ experiment = Growthbook::Experiment.new("my-test", 2, coverage: 0.4)
71
+ var0 = 0
72
+ var1 = 0
73
+ varn = 0
74
+ for i in 0..999
75
+ result = Growthbook::Util.chooseVariation(i.to_s, experiment)
76
+ case result
77
+ when -1
78
+ varn += 1
79
+ when 0
80
+ var0 += 1
81
+ else
82
+ var1 += 1
83
+ end
84
+ end
85
+ expect(var0).to eq(200)
86
+ expect(var1).to eq(204)
87
+ expect(varn).to eq(596)
88
+ end
89
+
90
+ it "assigns variations with default weights" do
91
+ experiment = Growthbook::Experiment.new("my-test", 2)
92
+
93
+ expect(Growthbook::Util.chooseVariation('1', experiment)).to eq(1)
94
+ expect(Growthbook::Util.chooseVariation('2', experiment)).to eq(0)
95
+ expect(Growthbook::Util.chooseVariation('3', experiment)).to eq(0)
96
+ expect(Growthbook::Util.chooseVariation('4', experiment)).to eq(1)
97
+ expect(Growthbook::Util.chooseVariation('5', experiment)).to eq(1)
98
+ expect(Growthbook::Util.chooseVariation('6', experiment)).to eq(1)
99
+ expect(Growthbook::Util.chooseVariation('7', experiment)).to eq(0)
100
+ expect(Growthbook::Util.chooseVariation('8', experiment)).to eq(1)
101
+ expect(Growthbook::Util.chooseVariation('9', experiment)).to eq(0)
102
+ end
103
+
104
+ it "assigns variations with uneven weights" do
105
+ experiment = Growthbook::Experiment.new("my-test", 2, weights: [0.1, 0.9])
106
+
107
+ expect(Growthbook::Util.chooseVariation('1', experiment)).to eq(1)
108
+ expect(Growthbook::Util.chooseVariation('2', experiment)).to eq(1)
109
+ expect(Growthbook::Util.chooseVariation('3', experiment)).to eq(0)
110
+ expect(Growthbook::Util.chooseVariation('4', experiment)).to eq(1)
111
+ expect(Growthbook::Util.chooseVariation('5', experiment)).to eq(1)
112
+ expect(Growthbook::Util.chooseVariation('6', experiment)).to eq(1)
113
+ expect(Growthbook::Util.chooseVariation('7', experiment)).to eq(0)
114
+ expect(Growthbook::Util.chooseVariation('8', experiment)).to eq(1)
115
+ expect(Growthbook::Util.chooseVariation('9', experiment)).to eq(1)
116
+ end
117
+
118
+ it "assigns variations with reduced coverage" do
119
+ experiment = Growthbook::Experiment.new("my-test", 2, coverage: 0.4)
120
+
121
+ expect(Growthbook::Util.chooseVariation('1', experiment)).to eq(-1)
122
+ expect(Growthbook::Util.chooseVariation('2', experiment)).to eq(0)
123
+ expect(Growthbook::Util.chooseVariation('3', experiment)).to eq(0)
124
+ expect(Growthbook::Util.chooseVariation('4', experiment)).to eq(-1)
125
+ expect(Growthbook::Util.chooseVariation('5', experiment)).to eq(-1)
126
+ expect(Growthbook::Util.chooseVariation('6', experiment)).to eq(-1)
127
+ expect(Growthbook::Util.chooseVariation('7', experiment)).to eq(0)
128
+ expect(Growthbook::Util.chooseVariation('8', experiment)).to eq(-1)
129
+ expect(Growthbook::Util.chooseVariation('9', experiment)).to eq(1)
130
+ end
131
+
132
+ it "assigns variations with default 3 variations" do
133
+ experiment = Growthbook::Experiment.new("my-test", 3)
134
+
135
+ expect(Growthbook::Util.chooseVariation('1', experiment)).to eq(2)
136
+ expect(Growthbook::Util.chooseVariation('2', experiment)).to eq(0)
137
+ expect(Growthbook::Util.chooseVariation('3', experiment)).to eq(0)
138
+ expect(Growthbook::Util.chooseVariation('4', experiment)).to eq(2)
139
+ expect(Growthbook::Util.chooseVariation('5', experiment)).to eq(1)
140
+ expect(Growthbook::Util.chooseVariation('6', experiment)).to eq(2)
141
+ expect(Growthbook::Util.chooseVariation('7', experiment)).to eq(0)
142
+ expect(Growthbook::Util.chooseVariation('8', experiment)).to eq(1)
143
+ expect(Growthbook::Util.chooseVariation('9', experiment)).to eq(0)
144
+ end
145
+
146
+ it "uses experiment name to choose a variation" do
147
+ experiment1 = Growthbook::Experiment.new("my-test", 2)
148
+ experiment2 = Growthbook::Experiment.new("my-test-3", 2)
149
+
150
+ expect(Growthbook::Util.chooseVariation('1', experiment1)).to eq(1)
151
+ expect(Growthbook::Util.chooseVariation('1', experiment2)).to eq(0)
152
+ end
153
+ end
154
+ end