Skip to content

Commit 0f25614

Browse files
committed
tests
1 parent 939691c commit 0f25614

12 files changed

Lines changed: 3853 additions & 0 deletions

Rakefile

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
require "rspec/core/rake_task"
2+
3+
RSpec::Core::RakeTask.new(:spec)
4+
5+
task default: :spec
6+
7+
desc "Build the gem"
8+
task :build do
9+
system "gem build featurevisor.gemspec"
10+
end
11+
12+
desc "Install the gem locally"
13+
task :install => :build do
14+
system "gem install featurevisor-*.gem"
15+
end
16+
17+
desc "Clean up built gems"
18+
task :clean do
19+
FileUtils.rm_f Dir["*.gem"]
20+
end

spec/bucketer_spec.rb

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
require "featurevisor"
2+
3+
RSpec.describe Featurevisor::Bucketer do
4+
describe "get_bucketed_number" do
5+
it "should be a method" do
6+
expect(Featurevisor::Bucketer).to respond_to(:get_bucketed_number)
7+
end
8+
9+
it "should return a number between 0 and 100000" do
10+
keys = ["foo", "bar", "baz", "123adshlk348-93asdlk"]
11+
12+
keys.each do |key|
13+
n = Featurevisor::Bucketer.get_bucketed_number(key)
14+
15+
expect(n).to be >= 0
16+
expect(n).to be <= Featurevisor::Bucketer::MAX_BUCKETED_NUMBER
17+
end
18+
end
19+
20+
# These assertions will be copied to unit tests of SDKs ported to other languages,
21+
# so we can keep consistent bucketing across all SDKs
22+
it "should return expected number for known keys" do
23+
expected_results = {
24+
"foo" => 20_602,
25+
"bar" => 89_144,
26+
"123.foo" => 3_151,
27+
"123.bar" => 9_710,
28+
"123.456.foo" => 14_432,
29+
"123.456.bar" => 1_982
30+
}
31+
32+
expected_results.each do |key, expected_value|
33+
n = Featurevisor::Bucketer.get_bucketed_number(key)
34+
35+
expect(n).to eq(expected_value)
36+
end
37+
end
38+
end
39+
40+
describe "get_bucket_key" do
41+
let(:logger) { Featurevisor.create_logger(level: "warn") }
42+
43+
it "should be a method" do
44+
expect(Featurevisor::Bucketer).to respond_to(:get_bucket_key)
45+
end
46+
47+
it "plain: should return a bucket key for a plain bucketBy" do
48+
feature_key = "test-feature"
49+
bucket_by = "userId"
50+
context = { userId: "123", browser: "chrome" }
51+
52+
bucket_key = Featurevisor::Bucketer.get_bucket_key(
53+
feature_key: feature_key,
54+
bucket_by: bucket_by,
55+
context: context,
56+
logger: logger
57+
)
58+
59+
expect(bucket_key).to eq("123.test-feature")
60+
end
61+
62+
it "plain: should return a bucket key with feature key only if value is missing in context" do
63+
feature_key = "test-feature"
64+
bucket_by = "userId"
65+
context = { browser: "chrome" }
66+
67+
bucket_key = Featurevisor::Bucketer.get_bucket_key(
68+
feature_key: feature_key,
69+
bucket_by: bucket_by,
70+
context: context,
71+
logger: logger
72+
)
73+
74+
expect(bucket_key).to eq("test-feature")
75+
end
76+
77+
it "and: should combine multiple field values together if present" do
78+
feature_key = "test-feature"
79+
bucket_by = ["organizationId", "userId"]
80+
context = { organizationId: "123", userId: "234", browser: "chrome" }
81+
82+
bucket_key = Featurevisor::Bucketer.get_bucket_key(
83+
feature_key: feature_key,
84+
bucket_by: bucket_by,
85+
context: context,
86+
logger: logger
87+
)
88+
89+
expect(bucket_key).to eq("123.234.test-feature")
90+
end
91+
92+
it "and: should combine only available field values together if present" do
93+
feature_key = "test-feature"
94+
bucket_by = ["organizationId", "userId"]
95+
context = { organizationId: "123", browser: "chrome" }
96+
97+
bucket_key = Featurevisor::Bucketer.get_bucket_key(
98+
feature_key: feature_key,
99+
bucket_by: bucket_by,
100+
context: context,
101+
logger: logger
102+
)
103+
104+
expect(bucket_key).to eq("123.test-feature")
105+
end
106+
107+
it "and: should combine all available fields, with dot separated paths" do
108+
feature_key = "test-feature"
109+
bucket_by = ["organizationId", "user.id"]
110+
context = {
111+
organizationId: "123",
112+
user: {
113+
id: "234"
114+
},
115+
browser: "chrome"
116+
}
117+
118+
bucket_key = Featurevisor::Bucketer.get_bucket_key(
119+
feature_key: feature_key,
120+
bucket_by: bucket_by,
121+
context: context,
122+
logger: logger
123+
)
124+
125+
expect(bucket_key).to eq("123.234.test-feature")
126+
end
127+
128+
it "or: should take first available field value" do
129+
feature_key = "test-feature"
130+
bucket_by = { or: ["userId", "deviceId"] }
131+
context = { deviceId: "deviceIdHere", userId: "234", browser: "chrome" }
132+
133+
bucket_key = Featurevisor::Bucketer.get_bucket_key(
134+
feature_key: feature_key,
135+
bucket_by: bucket_by,
136+
context: context,
137+
logger: logger
138+
)
139+
140+
expect(bucket_key).to eq("234.test-feature")
141+
end
142+
143+
it "or: should take first available field value when userId is missing" do
144+
feature_key = "test-feature"
145+
bucket_by = { or: ["userId", "deviceId"] }
146+
context = { deviceId: "deviceIdHere", browser: "chrome" }
147+
148+
bucket_key = Featurevisor::Bucketer.get_bucket_key(
149+
feature_key: feature_key,
150+
bucket_by: bucket_by,
151+
context: context,
152+
logger: logger
153+
)
154+
155+
expect(bucket_key).to eq("deviceIdHere.test-feature")
156+
end
157+
158+
it "should raise error for invalid bucketBy" do
159+
feature_key = "test-feature"
160+
bucket_by = { invalid: "config" }
161+
context = { userId: "123" }
162+
163+
expect do
164+
Featurevisor::Bucketer.get_bucket_key(
165+
feature_key: feature_key,
166+
bucket_by: bucket_by,
167+
context: context,
168+
logger: logger
169+
)
170+
end.to raise_error(StandardError, "invalid bucketBy")
171+
end
172+
end
173+
174+
describe "constants" do
175+
it "should have MAX_BUCKETED_NUMBER constant" do
176+
expect(Featurevisor::Bucketer::MAX_BUCKETED_NUMBER).to eq(100_000)
177+
end
178+
179+
it "should have HASH_SEED constant" do
180+
expect(Featurevisor::Bucketer::HASH_SEED).to eq(1)
181+
end
182+
183+
it "should have MAX_HASH_VALUE constant" do
184+
expect(Featurevisor::Bucketer::MAX_HASH_VALUE).to eq(2**32)
185+
end
186+
187+
it "should have DEFAULT_BUCKET_KEY_SEPARATOR constant" do
188+
expect(Featurevisor::Bucketer::DEFAULT_BUCKET_KEY_SEPARATOR).to eq(".")
189+
end
190+
end
191+
end

0 commit comments

Comments
 (0)