launchdarkly-server-sdk 6.2.1 → 6.2.5

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 (82) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -3
  3. data/lib/ldclient-rb/config.rb +3 -3
  4. data/lib/ldclient-rb/impl/diagnostic_events.rb +1 -1
  5. data/lib/ldclient-rb/integrations/dynamodb.rb +1 -1
  6. data/lib/ldclient-rb/integrations/redis.rb +1 -1
  7. data/lib/ldclient-rb/interfaces.rb +1 -1
  8. data/lib/ldclient-rb/ldclient.rb +5 -5
  9. data/lib/ldclient-rb/requestor.rb +1 -1
  10. data/lib/ldclient-rb/version.rb +1 -1
  11. metadata +24 -132
  12. data/.circleci/config.yml +0 -40
  13. data/.github/ISSUE_TEMPLATE/bug_report.md +0 -37
  14. data/.github/ISSUE_TEMPLATE/config.yml +0 -5
  15. data/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
  16. data/.github/pull_request_template.md +0 -21
  17. data/.gitignore +0 -16
  18. data/.hound.yml +0 -2
  19. data/.ldrelease/build-docs.sh +0 -18
  20. data/.ldrelease/circleci/linux/execute.sh +0 -18
  21. data/.ldrelease/circleci/mac/execute.sh +0 -18
  22. data/.ldrelease/circleci/template/build.sh +0 -29
  23. data/.ldrelease/circleci/template/publish.sh +0 -23
  24. data/.ldrelease/circleci/template/set-gem-home.sh +0 -7
  25. data/.ldrelease/circleci/template/test.sh +0 -10
  26. data/.ldrelease/circleci/template/update-version.sh +0 -8
  27. data/.ldrelease/circleci/windows/execute.ps1 +0 -19
  28. data/.ldrelease/config.yml +0 -29
  29. data/.rspec +0 -2
  30. data/.rubocop.yml +0 -600
  31. data/.simplecov +0 -4
  32. data/CHANGELOG.md +0 -359
  33. data/CODEOWNERS +0 -1
  34. data/CONTRIBUTING.md +0 -37
  35. data/Gemfile +0 -3
  36. data/azure-pipelines.yml +0 -51
  37. data/docs/Makefile +0 -26
  38. data/docs/index.md +0 -9
  39. data/launchdarkly-server-sdk.gemspec +0 -45
  40. data/spec/config_spec.rb +0 -63
  41. data/spec/diagnostic_events_spec.rb +0 -163
  42. data/spec/evaluation_detail_spec.rb +0 -135
  43. data/spec/event_sender_spec.rb +0 -197
  44. data/spec/event_summarizer_spec.rb +0 -63
  45. data/spec/events_spec.rb +0 -607
  46. data/spec/expiring_cache_spec.rb +0 -76
  47. data/spec/feature_store_spec_base.rb +0 -213
  48. data/spec/file_data_source_spec.rb +0 -283
  49. data/spec/fixtures/feature.json +0 -37
  50. data/spec/fixtures/feature1.json +0 -36
  51. data/spec/fixtures/user.json +0 -9
  52. data/spec/flags_state_spec.rb +0 -81
  53. data/spec/http_util.rb +0 -132
  54. data/spec/impl/evaluator_bucketing_spec.rb +0 -216
  55. data/spec/impl/evaluator_clause_spec.rb +0 -55
  56. data/spec/impl/evaluator_operators_spec.rb +0 -141
  57. data/spec/impl/evaluator_rule_spec.rb +0 -128
  58. data/spec/impl/evaluator_segment_spec.rb +0 -125
  59. data/spec/impl/evaluator_spec.rb +0 -349
  60. data/spec/impl/evaluator_spec_base.rb +0 -75
  61. data/spec/impl/event_factory_spec.rb +0 -108
  62. data/spec/impl/model/serialization_spec.rb +0 -41
  63. data/spec/in_memory_feature_store_spec.rb +0 -12
  64. data/spec/integrations/consul_feature_store_spec.rb +0 -40
  65. data/spec/integrations/dynamodb_feature_store_spec.rb +0 -103
  66. data/spec/integrations/store_wrapper_spec.rb +0 -276
  67. data/spec/launchdarkly-server-sdk_spec.rb +0 -13
  68. data/spec/launchdarkly-server-sdk_spec_autoloadtest.rb +0 -9
  69. data/spec/ldclient_end_to_end_spec.rb +0 -157
  70. data/spec/ldclient_spec.rb +0 -635
  71. data/spec/newrelic_spec.rb +0 -5
  72. data/spec/polling_spec.rb +0 -120
  73. data/spec/redis_feature_store_spec.rb +0 -121
  74. data/spec/requestor_spec.rb +0 -196
  75. data/spec/segment_store_spec_base.rb +0 -95
  76. data/spec/simple_lru_cache_spec.rb +0 -24
  77. data/spec/spec_helper.rb +0 -9
  78. data/spec/store_spec.rb +0 -10
  79. data/spec/stream_spec.rb +0 -45
  80. data/spec/user_filter_spec.rb +0 -91
  81. data/spec/util_spec.rb +0 -17
  82. data/spec/version_spec.rb +0 -7
@@ -1,635 +0,0 @@
1
- require "spec_helper"
2
-
3
-
4
- describe LaunchDarkly::LDClient do
5
- subject { LaunchDarkly::LDClient }
6
- let(:offline_config) { LaunchDarkly::Config.new({offline: true}) }
7
- let(:offline_client) do
8
- subject.new("secret", offline_config)
9
- end
10
- let(:null_data) { LaunchDarkly::NullUpdateProcessor.new }
11
- let(:logger) { double().as_null_object }
12
- let(:config) { LaunchDarkly::Config.new({ send_events: false, data_source: null_data, logger: logger }) }
13
- let(:client) do
14
- subject.new("secret", config)
15
- end
16
- let(:feature) do
17
- data = File.read(File.join("spec", "fixtures", "feature.json"))
18
- JSON.parse(data, symbolize_names: true)
19
- end
20
- let(:user) do
21
- {
22
- key: "user@test.com",
23
- custom: {
24
- groups: [ "microsoft", "google" ]
25
- }
26
- }
27
- end
28
- let(:user_anonymous) do
29
- {
30
- key: "anonymous@test.com",
31
- anonymous: true
32
- }
33
- end
34
- let(:numeric_key_user) do
35
- {
36
- key: 33,
37
- custom: {
38
- groups: [ "microsoft", "google" ]
39
- }
40
- }
41
- end
42
- let(:sanitized_numeric_key_user) do
43
- {
44
- key: "33",
45
- custom: {
46
- groups: [ "microsoft", "google" ]
47
- }
48
- }
49
- end
50
- let(:user_without_key) do
51
- { name: "Keyless Joe" }
52
- end
53
-
54
- def event_processor
55
- client.instance_variable_get(:@event_processor)
56
- end
57
-
58
- describe "constructor requirement of non-nil sdk key" do
59
- it "is not enforced when offline" do
60
- subject.new(nil, offline_config)
61
- end
62
-
63
- it "is not enforced if use_ldd is true and send_events is false" do
64
- subject.new(nil, LaunchDarkly::Config.new({ use_ldd: true, send_events: false }))
65
- end
66
-
67
- it "is not enforced if using file data and send_events is false" do
68
- source = LaunchDarkly::FileDataSource.factory({})
69
- subject.new(nil, LaunchDarkly::Config.new({ data_source: source, send_events: false }))
70
- end
71
-
72
- it "is enforced in streaming mode even if send_events is false" do
73
- expect {
74
- subject.new(nil, LaunchDarkly::Config.new({ send_events: false }))
75
- }.to raise_error(ArgumentError)
76
- end
77
-
78
- it "is enforced in polling mode even if send_events is false" do
79
- expect {
80
- subject.new(nil, LaunchDarkly::Config.new({ stream: false, send_events: false }))
81
- }.to raise_error(ArgumentError)
82
- end
83
-
84
- it "is enforced if use_ldd is true and send_events is true" do
85
- expect {
86
- subject.new(nil, LaunchDarkly::Config.new({ use_ldd: true }))
87
- }.to raise_error(ArgumentError)
88
- end
89
-
90
- it "is enforced if using file data and send_events is true" do
91
- source = LaunchDarkly::FileDataSource.factory({})
92
- expect {
93
- subject.new(nil, LaunchDarkly::Config.new({ data_source: source }))
94
- }.to raise_error(ArgumentError)
95
- end
96
- end
97
-
98
- describe '#variation' do
99
- feature_with_value = { key: "key", on: false, offVariation: 0, variations: ["value"], version: 100,
100
- trackEvents: true, debugEventsUntilDate: 1000 }
101
-
102
- it "returns the default value if the client is offline" do
103
- result = offline_client.variation("doesntmatter", user, "default")
104
- expect(result).to eq "default"
105
- end
106
-
107
- it "returns the default value for an unknown feature" do
108
- expect(client.variation("badkey", user, "default")).to eq "default"
109
- end
110
-
111
- it "queues a feature request event for an unknown feature" do
112
- expect(event_processor).to receive(:add_event).with(hash_including(
113
- kind: "feature", key: "badkey", user: user, value: "default", default: "default"
114
- ))
115
- client.variation("badkey", user, "default")
116
- end
117
-
118
- it "returns the value for an existing feature" do
119
- config.feature_store.init({ LaunchDarkly::FEATURES => {} })
120
- config.feature_store.upsert(LaunchDarkly::FEATURES, feature_with_value)
121
- expect(client.variation("key", user, "default")).to eq "value"
122
- end
123
-
124
- it "returns the default value if a feature evaluates to nil" do
125
- empty_feature = { key: "key", on: false, offVariation: nil }
126
- config.feature_store.init({ LaunchDarkly::FEATURES => {} })
127
- config.feature_store.upsert(LaunchDarkly::FEATURES, empty_feature)
128
- expect(client.variation("key", user, "default")).to eq "default"
129
- end
130
-
131
- it "queues a feature request event for an existing feature" do
132
- config.feature_store.init({ LaunchDarkly::FEATURES => {} })
133
- config.feature_store.upsert(LaunchDarkly::FEATURES, feature_with_value)
134
- expect(event_processor).to receive(:add_event).with(hash_including(
135
- kind: "feature",
136
- key: "key",
137
- version: 100,
138
- user: user,
139
- variation: 0,
140
- value: "value",
141
- default: "default",
142
- trackEvents: true,
143
- debugEventsUntilDate: 1000
144
- ))
145
- client.variation("key", user, "default")
146
- end
147
-
148
- it "does not send an event if user is nil" do
149
- config.feature_store.init({ LaunchDarkly::FEATURES => {} })
150
- config.feature_store.upsert(LaunchDarkly::FEATURES, feature_with_value)
151
- expect(event_processor).not_to receive(:add_event)
152
- expect(logger).to receive(:error)
153
- client.variation("key", nil, "default")
154
- end
155
-
156
- it "queues a feature event for an existing feature when user is anonymous" do
157
- config.feature_store.init({ LaunchDarkly::FEATURES => {} })
158
- config.feature_store.upsert(LaunchDarkly::FEATURES, feature_with_value)
159
- expect(event_processor).to receive(:add_event).with(hash_including(
160
- kind: "feature",
161
- key: "key",
162
- version: 100,
163
- contextKind: "anonymousUser",
164
- user: user_anonymous,
165
- variation: 0,
166
- value: "value",
167
- default: "default",
168
- trackEvents: true,
169
- debugEventsUntilDate: 1000
170
- ))
171
- client.variation("key", user_anonymous, "default")
172
- end
173
-
174
- it "does not queue a feature event for an existing feature when user key is nil" do
175
- config.feature_store.init({ LaunchDarkly::FEATURES => {} })
176
- config.feature_store.upsert(LaunchDarkly::FEATURES, feature_with_value)
177
- bad_user = { name: "Bob" }
178
- expect(event_processor).not_to receive(:add_event)
179
- expect(logger).to receive(:warn)
180
- client.variation("key", bad_user, "default")
181
- end
182
-
183
- it "sets trackEvents and reason if trackEvents is set for matched rule" do
184
- flag = {
185
- key: 'flag',
186
- on: true,
187
- variations: [ 'value' ],
188
- version: 100,
189
- rules: [
190
- clauses: [
191
- { attribute: 'key', op: 'in', values: [ user[:key] ] }
192
- ],
193
- variation: 0,
194
- id: 'id',
195
- trackEvents: true
196
- ]
197
- }
198
- config.feature_store.init({ LaunchDarkly::FEATURES => {} })
199
- config.feature_store.upsert(LaunchDarkly::FEATURES, flag)
200
- expect(event_processor).to receive(:add_event).with(hash_including(
201
- kind: 'feature',
202
- key: 'flag',
203
- version: 100,
204
- user: user,
205
- value: 'value',
206
- default: 'default',
207
- trackEvents: true,
208
- reason: LaunchDarkly::EvaluationReason::rule_match(0, 'id')
209
- ))
210
- client.variation('flag', user, 'default')
211
- end
212
-
213
- it "sets trackEvents and reason if trackEventsFallthrough is set and we fell through" do
214
- flag = {
215
- key: 'flag',
216
- on: true,
217
- variations: [ 'value' ],
218
- fallthrough: { variation: 0 },
219
- version: 100,
220
- rules: [],
221
- trackEventsFallthrough: true
222
- }
223
- config.feature_store.init({ LaunchDarkly::FEATURES => {} })
224
- config.feature_store.upsert(LaunchDarkly::FEATURES, flag)
225
- expect(event_processor).to receive(:add_event).with(hash_including(
226
- kind: 'feature',
227
- key: 'flag',
228
- version: 100,
229
- user: user,
230
- value: 'value',
231
- default: 'default',
232
- trackEvents: true,
233
- reason: LaunchDarkly::EvaluationReason::fallthrough
234
- ))
235
- client.variation('flag', user, 'default')
236
- end
237
- end
238
-
239
- describe '#variation_detail' do
240
- feature_with_value = { key: "key", on: false, offVariation: 0, variations: ["value"], version: 100,
241
- trackEvents: true, debugEventsUntilDate: 1000 }
242
-
243
- it "returns the default value if the client is offline" do
244
- result = offline_client.variation_detail("doesntmatter", user, "default")
245
- expected = LaunchDarkly::EvaluationDetail.new("default", nil,
246
- LaunchDarkly::EvaluationReason::error(LaunchDarkly::EvaluationReason::ERROR_CLIENT_NOT_READY))
247
- expect(result).to eq expected
248
- end
249
-
250
- it "returns the default value for an unknown feature" do
251
- result = client.variation_detail("badkey", user, "default")
252
- expected = LaunchDarkly::EvaluationDetail.new("default", nil,
253
- LaunchDarkly::EvaluationReason::error(LaunchDarkly::EvaluationReason::ERROR_FLAG_NOT_FOUND))
254
- expect(result).to eq expected
255
- end
256
-
257
- it "queues a feature request event for an unknown feature" do
258
- expect(event_processor).to receive(:add_event).with(hash_including(
259
- kind: "feature", key: "badkey", user: user, value: "default", default: "default",
260
- reason: LaunchDarkly::EvaluationReason::error(LaunchDarkly::EvaluationReason::ERROR_FLAG_NOT_FOUND)
261
- ))
262
- client.variation_detail("badkey", user, "default")
263
- end
264
-
265
- it "returns a value for an existing feature" do
266
- config.feature_store.init({ LaunchDarkly::FEATURES => {} })
267
- config.feature_store.upsert(LaunchDarkly::FEATURES, feature_with_value)
268
- result = client.variation_detail("key", user, "default")
269
- expected = LaunchDarkly::EvaluationDetail.new("value", 0, LaunchDarkly::EvaluationReason::off)
270
- expect(result).to eq expected
271
- end
272
-
273
- it "returns the default value if a feature evaluates to nil" do
274
- empty_feature = { key: "key", on: false, offVariation: nil }
275
- config.feature_store.init({ LaunchDarkly::FEATURES => {} })
276
- config.feature_store.upsert(LaunchDarkly::FEATURES, empty_feature)
277
- result = client.variation_detail("key", user, "default")
278
- expected = LaunchDarkly::EvaluationDetail.new("default", nil, LaunchDarkly::EvaluationReason::off)
279
- expect(result).to eq expected
280
- expect(result.default_value?).to be true
281
- end
282
-
283
- it "queues a feature request event for an existing feature" do
284
- config.feature_store.init({ LaunchDarkly::FEATURES => {} })
285
- config.feature_store.upsert(LaunchDarkly::FEATURES, feature_with_value)
286
- expect(event_processor).to receive(:add_event).with(hash_including(
287
- kind: "feature",
288
- key: "key",
289
- version: 100,
290
- user: user,
291
- variation: 0,
292
- value: "value",
293
- default: "default",
294
- trackEvents: true,
295
- debugEventsUntilDate: 1000,
296
- reason: LaunchDarkly::EvaluationReason::off
297
- ))
298
- client.variation_detail("key", user, "default")
299
- end
300
-
301
- it "does not send an event if user is nil" do
302
- config.feature_store.init({ LaunchDarkly::FEATURES => {} })
303
- config.feature_store.upsert(LaunchDarkly::FEATURES, feature_with_value)
304
- expect(event_processor).not_to receive(:add_event)
305
- expect(logger).to receive(:error)
306
- client.variation_detail("key", nil, "default")
307
- end
308
- end
309
-
310
- describe '#all_flags' do
311
- let(:flag1) { { key: "key1", offVariation: 0, variations: [ 'value1' ] } }
312
- let(:flag2) { { key: "key2", offVariation: 0, variations: [ 'value2' ] } }
313
-
314
- it "returns flag values" do
315
- config.feature_store.init({ LaunchDarkly::FEATURES => { 'key1' => flag1, 'key2' => flag2 } })
316
-
317
- result = client.all_flags({ key: 'userkey' })
318
- expect(result).to eq({ 'key1' => 'value1', 'key2' => 'value2' })
319
- end
320
-
321
- it "returns empty map for nil user" do
322
- config.feature_store.init({ LaunchDarkly::FEATURES => { 'key1' => flag1, 'key2' => flag2 } })
323
-
324
- result = client.all_flags(nil)
325
- expect(result).to eq({})
326
- end
327
-
328
- it "returns empty map for nil user key" do
329
- config.feature_store.init({ LaunchDarkly::FEATURES => { 'key1' => flag1, 'key2' => flag2 } })
330
-
331
- result = client.all_flags({})
332
- expect(result).to eq({})
333
- end
334
-
335
- it "returns empty map if offline" do
336
- offline_config.feature_store.init({ LaunchDarkly::FEATURES => { 'key1' => flag1, 'key2' => flag2 } })
337
-
338
- result = offline_client.all_flags(nil)
339
- expect(result).to eq({})
340
- end
341
- end
342
-
343
- describe '#all_flags_state' do
344
- let(:flag1) { { key: "key1", version: 100, offVariation: 0, variations: [ 'value1' ], trackEvents: false } }
345
- let(:flag2) { { key: "key2", version: 200, offVariation: 1, variations: [ 'x', 'value2' ], trackEvents: true, debugEventsUntilDate: 1000 } }
346
-
347
- it "returns flags state" do
348
- config.feature_store.init({ LaunchDarkly::FEATURES => { 'key1' => flag1, 'key2' => flag2 } })
349
-
350
- state = client.all_flags_state({ key: 'userkey' })
351
- expect(state.valid?).to be true
352
-
353
- values = state.values_map
354
- expect(values).to eq({ 'key1' => 'value1', 'key2' => 'value2' })
355
-
356
- result = state.as_json
357
- expect(result).to eq({
358
- 'key1' => 'value1',
359
- 'key2' => 'value2',
360
- '$flagsState' => {
361
- 'key1' => {
362
- :variation => 0,
363
- :version => 100
364
- },
365
- 'key2' => {
366
- :variation => 1,
367
- :version => 200,
368
- :trackEvents => true,
369
- :debugEventsUntilDate => 1000
370
- }
371
- },
372
- '$valid' => true
373
- })
374
- end
375
-
376
- it "can be filtered for only client-side flags" do
377
- flag1 = { key: "server-side-1", offVariation: 0, variations: [ 'a' ], clientSide: false }
378
- flag2 = { key: "server-side-2", offVariation: 0, variations: [ 'b' ], clientSide: false }
379
- flag3 = { key: "client-side-1", offVariation: 0, variations: [ 'value1' ], clientSide: true }
380
- flag4 = { key: "client-side-2", offVariation: 0, variations: [ 'value2' ], clientSide: true }
381
- config.feature_store.init({ LaunchDarkly::FEATURES => {
382
- flag1[:key] => flag1, flag2[:key] => flag2, flag3[:key] => flag3, flag4[:key] => flag4
383
- }})
384
-
385
- state = client.all_flags_state({ key: 'userkey' }, client_side_only: true)
386
- expect(state.valid?).to be true
387
-
388
- values = state.values_map
389
- expect(values).to eq({ 'client-side-1' => 'value1', 'client-side-2' => 'value2' })
390
- end
391
-
392
- it "can omit details for untracked flags" do
393
- future_time = (Time.now.to_f * 1000).to_i + 100000
394
- flag1 = { key: "key1", version: 100, offVariation: 0, variations: [ 'value1' ], trackEvents: false }
395
- flag2 = { key: "key2", version: 200, offVariation: 1, variations: [ 'x', 'value2' ], trackEvents: true }
396
- flag3 = { key: "key3", version: 300, offVariation: 1, variations: [ 'x', 'value3' ], debugEventsUntilDate: future_time }
397
-
398
- config.feature_store.init({ LaunchDarkly::FEATURES => { 'key1' => flag1, 'key2' => flag2, 'key3' => flag3 } })
399
-
400
- state = client.all_flags_state({ key: 'userkey' }, { details_only_for_tracked_flags: true })
401
- expect(state.valid?).to be true
402
-
403
- values = state.values_map
404
- expect(values).to eq({ 'key1' => 'value1', 'key2' => 'value2', 'key3' => 'value3' })
405
-
406
- result = state.as_json
407
- expect(result).to eq({
408
- 'key1' => 'value1',
409
- 'key2' => 'value2',
410
- 'key3' => 'value3',
411
- '$flagsState' => {
412
- 'key1' => {
413
- :variation => 0
414
- },
415
- 'key2' => {
416
- :variation => 1,
417
- :version => 200,
418
- :trackEvents => true
419
- },
420
- 'key3' => {
421
- :variation => 1,
422
- :version => 300,
423
- :debugEventsUntilDate => future_time
424
- }
425
- },
426
- '$valid' => true
427
- })
428
- end
429
-
430
- it "returns empty state for nil user" do
431
- config.feature_store.init({ LaunchDarkly::FEATURES => { 'key1' => flag1, 'key2' => flag2 } })
432
-
433
- state = client.all_flags_state(nil)
434
- expect(state.valid?).to be false
435
- expect(state.values_map).to eq({})
436
- end
437
-
438
- it "returns empty state for nil user key" do
439
- config.feature_store.init({ LaunchDarkly::FEATURES => { 'key1' => flag1, 'key2' => flag2 } })
440
-
441
- state = client.all_flags_state({})
442
- expect(state.valid?).to be false
443
- expect(state.values_map).to eq({})
444
- end
445
-
446
- it "returns empty state if offline" do
447
- offline_config.feature_store.init({ LaunchDarkly::FEATURES => { 'key1' => flag1, 'key2' => flag2 } })
448
-
449
- state = offline_client.all_flags_state({ key: 'userkey' })
450
- expect(state.valid?).to be false
451
- expect(state.values_map).to eq({})
452
- end
453
- end
454
-
455
- describe '#secure_mode_hash' do
456
- it "will return the expected value for a known message and secret" do
457
- result = client.secure_mode_hash({key: :Message})
458
- expect(result).to eq "aa747c502a898200f9e4fa21bac68136f886a0e27aec70ba06daf2e2a5cb5597"
459
- end
460
- end
461
-
462
- describe '#track' do
463
- it "queues up an custom event" do
464
- expect(event_processor).to receive(:add_event).with(hash_including(kind: "custom", key: "custom_event_name", user: user, data: 42))
465
- client.track("custom_event_name", user, 42)
466
- end
467
-
468
- it "can include a metric value" do
469
- expect(event_processor).to receive(:add_event).with(hash_including(
470
- kind: "custom", key: "custom_event_name", user: user, metricValue: 1.5))
471
- client.track("custom_event_name", user, nil, 1.5)
472
- end
473
-
474
- it "includes contextKind with anonymous user" do
475
- expect(event_processor).to receive(:add_event).with(hash_including(
476
- kind: "custom", key: "custom_event_name", user: user_anonymous, metricValue: 2.2, contextKind: "anonymousUser"))
477
- client.track("custom_event_name", user_anonymous, nil, 2.2)
478
- end
479
-
480
- it "sanitizes the user in the event" do
481
- expect(event_processor).to receive(:add_event).with(hash_including(user: sanitized_numeric_key_user))
482
- client.track("custom_event_name", numeric_key_user, nil)
483
- end
484
-
485
- it "does not send an event, and logs a warning, if user is nil" do
486
- expect(event_processor).not_to receive(:add_event)
487
- expect(logger).to receive(:warn)
488
- client.track("custom_event_name", nil, nil)
489
- end
490
-
491
- it "does not send an event, and logs a warning, if user key is nil" do
492
- expect(event_processor).not_to receive(:add_event)
493
- expect(logger).to receive(:warn)
494
- client.track("custom_event_name", user_without_key, nil)
495
- end
496
- end
497
-
498
- describe '#alias' do
499
- it "queues up an alias event" do
500
- expect(event_processor).to receive(:add_event).with(hash_including(
501
- kind: "alias", key: user[:key], contextKind: "user", previousKey: user_anonymous[:key], previousContextKind: "anonymousUser"))
502
- client.alias(user, user_anonymous)
503
- end
504
-
505
- it "does not send an event, and logs a warning, if user is nil" do
506
- expect(event_processor).not_to receive(:add_event)
507
- expect(logger).to receive(:warn)
508
- client.alias(nil, nil)
509
- end
510
-
511
- it "does not send an event, and logs a warning, if user key is nil" do
512
- expect(event_processor).not_to receive(:add_event)
513
- expect(logger).to receive(:warn)
514
- client.alias(user_without_key, user_without_key)
515
- end
516
- end
517
-
518
- describe '#identify' do
519
- it "queues up an identify event" do
520
- expect(event_processor).to receive(:add_event).with(hash_including(kind: "identify", key: user[:key], user: user))
521
- client.identify(user)
522
- end
523
-
524
- it "does not send an event, and logs a warning, if user is nil" do
525
- expect(event_processor).not_to receive(:add_event)
526
- expect(logger).to receive(:warn)
527
- client.identify(nil)
528
- end
529
-
530
- it "does not send an event, and logs a warning, if user key is nil" do
531
- expect(event_processor).not_to receive(:add_event)
532
- expect(logger).to receive(:warn)
533
- client.identify(user_without_key)
534
- end
535
- end
536
-
537
- describe 'with send_events: false' do
538
- let(:config) { LaunchDarkly::Config.new({offline: true, send_events: false, data_source: null_data}) }
539
- let(:client) { subject.new("secret", config) }
540
-
541
- it "uses a NullEventProcessor" do
542
- ep = client.instance_variable_get(:@event_processor)
543
- expect(ep).to be_a(LaunchDarkly::NullEventProcessor)
544
- end
545
- end
546
-
547
- describe 'with send_events: true' do
548
- let(:config_with_events) { LaunchDarkly::Config.new({offline: false, send_events: true, diagnostic_opt_out: true, data_source: null_data}) }
549
- let(:client_with_events) { subject.new("secret", config_with_events) }
550
-
551
- it "does not use a NullEventProcessor" do
552
- ep = client_with_events.instance_variable_get(:@event_processor)
553
- expect(ep).not_to be_a(LaunchDarkly::NullEventProcessor)
554
- end
555
- end
556
-
557
- describe "feature store data ordering" do
558
- let(:dependency_ordering_test_data) {
559
- {
560
- LaunchDarkly::FEATURES => {
561
- a: { key: "a", prerequisites: [ { key: "b" }, { key: "c" } ] },
562
- b: { key: "b", prerequisites: [ { key: "c" }, { key: "e" } ] },
563
- c: { key: "c" },
564
- d: { key: "d" },
565
- e: { key: "e" },
566
- f: { key: "f" }
567
- },
568
- LaunchDarkly::SEGMENTS => {
569
- o: { key: "o" }
570
- }
571
- }
572
- }
573
-
574
- class FakeFeatureStore
575
- attr_reader :received_data
576
-
577
- def init(all_data)
578
- @received_data = all_data
579
- end
580
- end
581
-
582
- class FakeUpdateProcessor
583
- def initialize(store, data)
584
- @store = store
585
- @data = data
586
- end
587
-
588
- def start
589
- @store.init(@data)
590
- ev = Concurrent::Event.new
591
- ev.set
592
- ev
593
- end
594
-
595
- def stop
596
- end
597
-
598
- def initialized?
599
- true
600
- end
601
- end
602
-
603
- it "passes data set to feature store in correct order on init" do
604
- store = FakeFeatureStore.new
605
- data_source_factory = lambda { |sdk_key, config| FakeUpdateProcessor.new(config.feature_store,
606
- dependency_ordering_test_data) }
607
- config = LaunchDarkly::Config.new(send_events: false, feature_store: store, data_source: data_source_factory)
608
- client = subject.new("secret", config)
609
-
610
- data = store.received_data
611
- expect(data).not_to be_nil
612
- expect(data.count).to eq(2)
613
-
614
- # Segments should always come first
615
- expect(data.keys[0]).to be(LaunchDarkly::SEGMENTS)
616
- expect(data.values[0].count).to eq(dependency_ordering_test_data[LaunchDarkly::SEGMENTS].count)
617
-
618
- # Features should be ordered so that a flag always appears after its prerequisites, if any
619
- expect(data.keys[1]).to be(LaunchDarkly::FEATURES)
620
- flags_map = data.values[1]
621
- flags_list = flags_map.values
622
- expect(flags_list.count).to eq(dependency_ordering_test_data[LaunchDarkly::FEATURES].count)
623
- flags_list.each_with_index do |item, item_index|
624
- (item[:prerequisites] || []).each do |prereq|
625
- prereq = flags_map[prereq[:key].to_sym]
626
- prereq_index = flags_list.index(prereq)
627
- if prereq_index > item_index
628
- all_keys = (flags_list.map { |f| f[:key] }).join(", ")
629
- raise "#{item[:key]} depends on #{prereq[:key]}, but #{item[:key]} was listed first; keys in order are [#{all_keys}]"
630
- end
631
- end
632
- end
633
- end
634
- end
635
- end
@@ -1,5 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe LaunchDarkly::LDNewRelic do
4
- subject { LaunchDarkly::LDNewRelic }
5
- end