decision_agent 0.2.0 → 1.0.1

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 (126) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +313 -8
  3. data/bin/decision_agent +104 -0
  4. data/lib/decision_agent/agent.rb +72 -1
  5. data/lib/decision_agent/context.rb +1 -0
  6. data/lib/decision_agent/data_enrichment/cache/memory_adapter.rb +86 -0
  7. data/lib/decision_agent/data_enrichment/cache_adapter.rb +49 -0
  8. data/lib/decision_agent/data_enrichment/circuit_breaker.rb +135 -0
  9. data/lib/decision_agent/data_enrichment/client.rb +220 -0
  10. data/lib/decision_agent/data_enrichment/config.rb +78 -0
  11. data/lib/decision_agent/data_enrichment/errors.rb +36 -0
  12. data/lib/decision_agent/decision.rb +102 -2
  13. data/lib/decision_agent/dmn/adapter.rb +135 -0
  14. data/lib/decision_agent/dmn/cache.rb +306 -0
  15. data/lib/decision_agent/dmn/decision_graph.rb +327 -0
  16. data/lib/decision_agent/dmn/decision_tree.rb +192 -0
  17. data/lib/decision_agent/dmn/errors.rb +30 -0
  18. data/lib/decision_agent/dmn/exporter.rb +217 -0
  19. data/lib/decision_agent/dmn/feel/evaluator.rb +819 -0
  20. data/lib/decision_agent/dmn/feel/functions.rb +420 -0
  21. data/lib/decision_agent/dmn/feel/parser.rb +349 -0
  22. data/lib/decision_agent/dmn/feel/simple_parser.rb +276 -0
  23. data/lib/decision_agent/dmn/feel/transformer.rb +372 -0
  24. data/lib/decision_agent/dmn/feel/types.rb +276 -0
  25. data/lib/decision_agent/dmn/importer.rb +77 -0
  26. data/lib/decision_agent/dmn/model.rb +197 -0
  27. data/lib/decision_agent/dmn/parser.rb +191 -0
  28. data/lib/decision_agent/dmn/testing.rb +333 -0
  29. data/lib/decision_agent/dmn/validator.rb +315 -0
  30. data/lib/decision_agent/dmn/versioning.rb +229 -0
  31. data/lib/decision_agent/dmn/visualizer.rb +513 -0
  32. data/lib/decision_agent/dsl/condition_evaluator.rb +984 -838
  33. data/lib/decision_agent/dsl/schema_validator.rb +53 -14
  34. data/lib/decision_agent/evaluators/dmn_evaluator.rb +308 -0
  35. data/lib/decision_agent/evaluators/json_rule_evaluator.rb +69 -9
  36. data/lib/decision_agent/explainability/condition_trace.rb +83 -0
  37. data/lib/decision_agent/explainability/explainability_result.rb +52 -0
  38. data/lib/decision_agent/explainability/rule_trace.rb +39 -0
  39. data/lib/decision_agent/explainability/trace_collector.rb +24 -0
  40. data/lib/decision_agent/monitoring/alert_manager.rb +5 -1
  41. data/lib/decision_agent/simulation/errors.rb +18 -0
  42. data/lib/decision_agent/simulation/impact_analyzer.rb +498 -0
  43. data/lib/decision_agent/simulation/monte_carlo_simulator.rb +635 -0
  44. data/lib/decision_agent/simulation/replay_engine.rb +486 -0
  45. data/lib/decision_agent/simulation/scenario_engine.rb +318 -0
  46. data/lib/decision_agent/simulation/scenario_library.rb +163 -0
  47. data/lib/decision_agent/simulation/shadow_test_engine.rb +287 -0
  48. data/lib/decision_agent/simulation/what_if_analyzer.rb +1002 -0
  49. data/lib/decision_agent/simulation.rb +17 -0
  50. data/lib/decision_agent/version.rb +1 -1
  51. data/lib/decision_agent/versioning/activerecord_adapter.rb +23 -8
  52. data/lib/decision_agent/web/dmn_editor.rb +426 -0
  53. data/lib/decision_agent/web/public/app.js +119 -0
  54. data/lib/decision_agent/web/public/dmn-editor.css +596 -0
  55. data/lib/decision_agent/web/public/dmn-editor.html +250 -0
  56. data/lib/decision_agent/web/public/dmn-editor.js +553 -0
  57. data/lib/decision_agent/web/public/index.html +52 -0
  58. data/lib/decision_agent/web/public/simulation.html +130 -0
  59. data/lib/decision_agent/web/public/simulation_impact.html +478 -0
  60. data/lib/decision_agent/web/public/simulation_replay.html +551 -0
  61. data/lib/decision_agent/web/public/simulation_shadow.html +546 -0
  62. data/lib/decision_agent/web/public/simulation_whatif.html +532 -0
  63. data/lib/decision_agent/web/public/styles.css +86 -0
  64. data/lib/decision_agent/web/server.rb +1059 -23
  65. data/lib/decision_agent.rb +60 -2
  66. metadata +105 -61
  67. data/spec/ab_testing/ab_test_assignment_spec.rb +0 -253
  68. data/spec/ab_testing/ab_test_manager_spec.rb +0 -612
  69. data/spec/ab_testing/ab_test_spec.rb +0 -270
  70. data/spec/ab_testing/ab_testing_agent_spec.rb +0 -481
  71. data/spec/ab_testing/storage/adapter_spec.rb +0 -64
  72. data/spec/ab_testing/storage/memory_adapter_spec.rb +0 -485
  73. data/spec/activerecord_thread_safety_spec.rb +0 -553
  74. data/spec/advanced_operators_spec.rb +0 -3150
  75. data/spec/agent_spec.rb +0 -289
  76. data/spec/api_contract_spec.rb +0 -430
  77. data/spec/audit_adapters_spec.rb +0 -92
  78. data/spec/auth/access_audit_logger_spec.rb +0 -394
  79. data/spec/auth/authenticator_spec.rb +0 -112
  80. data/spec/auth/password_reset_spec.rb +0 -294
  81. data/spec/auth/permission_checker_spec.rb +0 -207
  82. data/spec/auth/permission_spec.rb +0 -73
  83. data/spec/auth/rbac_adapter_spec.rb +0 -550
  84. data/spec/auth/rbac_config_spec.rb +0 -82
  85. data/spec/auth/role_spec.rb +0 -51
  86. data/spec/auth/session_manager_spec.rb +0 -172
  87. data/spec/auth/session_spec.rb +0 -112
  88. data/spec/auth/user_spec.rb +0 -130
  89. data/spec/comprehensive_edge_cases_spec.rb +0 -1777
  90. data/spec/context_spec.rb +0 -127
  91. data/spec/decision_agent_spec.rb +0 -96
  92. data/spec/decision_spec.rb +0 -423
  93. data/spec/dsl/condition_evaluator_spec.rb +0 -774
  94. data/spec/dsl_validation_spec.rb +0 -648
  95. data/spec/edge_cases_spec.rb +0 -353
  96. data/spec/evaluation_spec.rb +0 -364
  97. data/spec/evaluation_validator_spec.rb +0 -165
  98. data/spec/examples/feedback_aware_evaluator_spec.rb +0 -460
  99. data/spec/examples.txt +0 -1633
  100. data/spec/issue_verification_spec.rb +0 -759
  101. data/spec/json_rule_evaluator_spec.rb +0 -587
  102. data/spec/monitoring/alert_manager_spec.rb +0 -378
  103. data/spec/monitoring/metrics_collector_spec.rb +0 -499
  104. data/spec/monitoring/monitored_agent_spec.rb +0 -222
  105. data/spec/monitoring/prometheus_exporter_spec.rb +0 -242
  106. data/spec/monitoring/storage/activerecord_adapter_spec.rb +0 -498
  107. data/spec/monitoring/storage/base_adapter_spec.rb +0 -61
  108. data/spec/monitoring/storage/memory_adapter_spec.rb +0 -247
  109. data/spec/performance_optimizations_spec.rb +0 -486
  110. data/spec/replay_edge_cases_spec.rb +0 -699
  111. data/spec/replay_spec.rb +0 -210
  112. data/spec/rfc8785_canonicalization_spec.rb +0 -215
  113. data/spec/scoring_spec.rb +0 -225
  114. data/spec/spec_helper.rb +0 -60
  115. data/spec/testing/batch_test_importer_spec.rb +0 -693
  116. data/spec/testing/batch_test_runner_spec.rb +0 -307
  117. data/spec/testing/test_coverage_analyzer_spec.rb +0 -292
  118. data/spec/testing/test_result_comparator_spec.rb +0 -392
  119. data/spec/testing/test_scenario_spec.rb +0 -113
  120. data/spec/thread_safety_spec.rb +0 -482
  121. data/spec/thread_safety_spec.rb.broken +0 -878
  122. data/spec/versioning/adapter_spec.rb +0 -156
  123. data/spec/versioning_spec.rb +0 -1030
  124. data/spec/web/middleware/auth_middleware_spec.rb +0 -133
  125. data/spec/web/middleware/permission_middleware_spec.rb +0 -247
  126. data/spec/web_ui_rack_spec.rb +0 -1840
@@ -1,481 +0,0 @@
1
- require "spec_helper"
2
-
3
- RSpec.describe DecisionAgent::ABTesting::ABTestingAgent do
4
- let(:version_manager) { double("VersionManager") }
5
- let(:ab_test_manager) { double("ABTestManager", version_manager: version_manager) }
6
- let(:base_evaluator) do
7
- DecisionAgent::Evaluators::StaticEvaluator.new(
8
- decision: "approve",
9
- weight: 0.8,
10
- reason: "Base evaluator"
11
- )
12
- end
13
-
14
- describe "#initialize" do
15
- it "initializes with ab_test_manager" do
16
- agent = described_class.new(ab_test_manager: ab_test_manager)
17
- expect(agent.ab_test_manager).to eq(ab_test_manager)
18
- end
19
-
20
- it "uses version_manager from ab_test_manager if not provided" do
21
- allow(ab_test_manager).to receive(:version_manager).and_return(version_manager)
22
- agent = described_class.new(ab_test_manager: ab_test_manager)
23
- expect(agent.version_manager).to eq(version_manager)
24
- end
25
-
26
- it "uses provided version_manager" do
27
- custom_version_manager = double("CustomVersionManager")
28
- agent = described_class.new(
29
- ab_test_manager: ab_test_manager,
30
- version_manager: custom_version_manager
31
- )
32
- expect(agent.version_manager).to eq(custom_version_manager)
33
- end
34
- end
35
-
36
- describe "#decide" do
37
- context "without A/B test" do
38
- it "makes standard decision" do
39
- agent = described_class.new(
40
- ab_test_manager: ab_test_manager,
41
- evaluators: [base_evaluator]
42
- )
43
-
44
- result = agent.decide(context: { user: "test" })
45
-
46
- expect(result[:decision]).to eq("approve")
47
- expect(result[:ab_test]).to be_nil
48
- end
49
- end
50
-
51
- context "with A/B test" do
52
- let(:assignment) do
53
- {
54
- assignment_id: "assign_1",
55
- variant: "A",
56
- version_id: "version_1"
57
- }
58
- end
59
-
60
- let(:version) do
61
- {
62
- content: {
63
- version: "1.0",
64
- ruleset: "test",
65
- rules: [
66
- {
67
- id: "rule_1",
68
- if: { field: "status", op: "eq", value: "active" },
69
- then: { decision: "approve", weight: 0.9 }
70
- }
71
- ]
72
- }
73
- }
74
- end
75
-
76
- before do
77
- allow(ab_test_manager).to receive(:assign_variant).and_return(assignment)
78
- allow(version_manager).to receive(:get_version).and_return(version)
79
- allow(ab_test_manager).to receive(:record_decision)
80
- end
81
-
82
- it "assigns variant and makes decision" do
83
- agent = described_class.new(
84
- ab_test_manager: ab_test_manager,
85
- version_manager: version_manager
86
- )
87
-
88
- result = agent.decide(
89
- context: { status: "active" },
90
- ab_test_id: "test_1",
91
- user_id: "user_1"
92
- )
93
-
94
- expect(result[:decision]).to eq("approve")
95
- expect(result[:ab_test]).not_to be_nil
96
- expect(result[:ab_test][:test_id]).to eq("test_1")
97
- expect(result[:ab_test][:variant]).to eq("A")
98
- end
99
-
100
- it "raises error if version not found" do
101
- allow(version_manager).to receive(:get_version).and_return(nil)
102
- agent = described_class.new(
103
- ab_test_manager: ab_test_manager,
104
- version_manager: version_manager
105
- )
106
-
107
- expect do
108
- agent.decide(
109
- context: { status: "active" },
110
- ab_test_id: "test_1"
111
- )
112
- end.to raise_error(DecisionAgent::ABTesting::VersionNotFoundError)
113
- end
114
-
115
- it "records decision result" do
116
- agent = described_class.new(
117
- ab_test_manager: ab_test_manager,
118
- version_manager: version_manager
119
- )
120
-
121
- agent.decide(
122
- context: { status: "active" },
123
- ab_test_id: "test_1"
124
- )
125
-
126
- expect(ab_test_manager).to have_received(:record_decision).with(
127
- assignment_id: "assign_1",
128
- decision: "approve",
129
- confidence: be_a(Numeric)
130
- )
131
- end
132
- end
133
- end
134
-
135
- describe "#get_test_results" do
136
- it "delegates to ab_test_manager" do
137
- agent = described_class.new(ab_test_manager: ab_test_manager)
138
- allow(ab_test_manager).to receive(:get_results).and_return({ results: [] })
139
-
140
- result = agent.get_test_results("test_1")
141
-
142
- expect(ab_test_manager).to have_received(:get_results).with("test_1")
143
- expect(result).to eq({ results: [] })
144
- end
145
- end
146
-
147
- describe "#active_tests" do
148
- it "delegates to ab_test_manager" do
149
- agent = described_class.new(ab_test_manager: ab_test_manager)
150
- allow(ab_test_manager).to receive(:active_tests).and_return([])
151
-
152
- result = agent.active_tests
153
-
154
- expect(ab_test_manager).to have_received(:active_tests)
155
- expect(result).to eq([])
156
- end
157
- end
158
-
159
- describe "#decide with feedback" do
160
- it "passes feedback to agent" do
161
- agent = described_class.new(
162
- ab_test_manager: ab_test_manager,
163
- evaluators: [base_evaluator]
164
- )
165
-
166
- result = agent.decide(context: { user: "test" }, feedback: { rating: 5 })
167
-
168
- expect(result[:decision]).to eq("approve")
169
- end
170
- end
171
-
172
- describe "#decide with A/B test - evaluator building" do
173
- let(:assignment) do
174
- {
175
- assignment_id: "assign_1",
176
- variant: "A",
177
- version_id: "version_1"
178
- }
179
- end
180
-
181
- let(:version_with_rules) do
182
- {
183
- content: {
184
- version: "1.0",
185
- ruleset: "test",
186
- rules: [
187
- {
188
- id: "rule_1",
189
- if: { field: "status", op: "eq", value: "active" },
190
- then: { decision: "approve", weight: 0.9 }
191
- }
192
- ]
193
- }
194
- }
195
- end
196
-
197
- let(:version_with_evaluators) do
198
- {
199
- content: {
200
- evaluators: [
201
- {
202
- type: "json_rule",
203
- rules: {
204
- version: "1.0",
205
- ruleset: "test",
206
- rules: [
207
- {
208
- id: "rule_1",
209
- if: { field: "status", op: "eq", value: "active" },
210
- then: { decision: "approve", weight: 0.9 }
211
- }
212
- ]
213
- }
214
- }
215
- ]
216
- }
217
- }
218
- end
219
-
220
- let(:version_with_static_evaluator) do
221
- {
222
- content: {
223
- evaluators: [
224
- {
225
- type: "static",
226
- decision: "reject",
227
- weight: 0.5,
228
- reason: "Static test"
229
- }
230
- ]
231
- }
232
- }
233
- end
234
-
235
- before do
236
- allow(ab_test_manager).to receive(:assign_variant).and_return(assignment)
237
- allow(ab_test_manager).to receive(:record_decision)
238
- end
239
-
240
- it "builds JsonRuleEvaluator from version with rules" do
241
- allow(version_manager).to receive(:get_version).and_return(version_with_rules)
242
- agent = described_class.new(
243
- ab_test_manager: ab_test_manager,
244
- version_manager: version_manager
245
- )
246
-
247
- result = agent.decide(
248
- context: { status: "active" },
249
- ab_test_id: "test_1"
250
- )
251
-
252
- expect(result[:decision]).to eq("approve")
253
- end
254
-
255
- it "builds evaluators from version with evaluator config" do
256
- allow(version_manager).to receive(:get_version).and_return(version_with_evaluators)
257
- agent = described_class.new(
258
- ab_test_manager: ab_test_manager,
259
- version_manager: version_manager
260
- )
261
-
262
- result = agent.decide(
263
- context: { status: "active" },
264
- ab_test_id: "test_1"
265
- )
266
-
267
- expect(result[:decision]).to eq("approve")
268
- end
269
-
270
- it "builds StaticEvaluator from version config" do
271
- allow(version_manager).to receive(:get_version).and_return(version_with_static_evaluator)
272
- agent = described_class.new(
273
- ab_test_manager: ab_test_manager,
274
- version_manager: version_manager
275
- )
276
-
277
- result = agent.decide(
278
- context: { status: "inactive" },
279
- ab_test_id: "test_1"
280
- )
281
-
282
- expect(result[:decision]).to eq("reject")
283
- end
284
-
285
- it "falls back to base evaluators when version content is invalid" do
286
- invalid_version = { content: "invalid" }
287
- allow(version_manager).to receive(:get_version).and_return(invalid_version)
288
- agent = described_class.new(
289
- ab_test_manager: ab_test_manager,
290
- version_manager: version_manager,
291
- evaluators: [base_evaluator]
292
- )
293
-
294
- result = agent.decide(
295
- context: { status: "active" },
296
- ab_test_id: "test_1"
297
- )
298
-
299
- expect(result[:decision]).to eq("approve")
300
- end
301
-
302
- it "raises error for unknown evaluator type" do
303
- invalid_evaluator_version = {
304
- content: {
305
- evaluators: [
306
- {
307
- type: "unknown_type",
308
- config: {}
309
- }
310
- ]
311
- }
312
- }
313
- allow(version_manager).to receive(:get_version).and_return(invalid_evaluator_version)
314
- agent = described_class.new(
315
- ab_test_manager: ab_test_manager,
316
- version_manager: version_manager
317
- )
318
-
319
- expect do
320
- agent.decide(
321
- context: { status: "active" },
322
- ab_test_id: "test_1"
323
- )
324
- end.to raise_error(/Unknown evaluator type/)
325
- end
326
- end
327
-
328
- describe "#decide with Context object" do
329
- it "handles Context object instead of hash" do
330
- agent = described_class.new(
331
- ab_test_manager: ab_test_manager,
332
- evaluators: [base_evaluator]
333
- )
334
-
335
- context = DecisionAgent::Context.new({ user: "test" })
336
- result = agent.decide(context: context)
337
-
338
- expect(result[:decision]).to eq("approve")
339
- end
340
- end
341
-
342
- describe "initialization with optional parameters" do
343
- it "initializes with scoring_strategy" do
344
- scoring_strategy = double("ScoringStrategy")
345
- agent = described_class.new(
346
- ab_test_manager: ab_test_manager,
347
- scoring_strategy: scoring_strategy
348
- )
349
-
350
- expect(agent.instance_variable_get(:@scoring_strategy)).to eq(scoring_strategy)
351
- end
352
-
353
- it "initializes with audit_adapter" do
354
- audit_adapter = double("AuditAdapter")
355
- agent = described_class.new(
356
- ab_test_manager: ab_test_manager,
357
- audit_adapter: audit_adapter
358
- )
359
-
360
- expect(agent.instance_variable_get(:@audit_adapter)).to eq(audit_adapter)
361
- end
362
- end
363
-
364
- describe "#build_agent" do
365
- it "uses base evaluators when provided evaluators are empty" do
366
- agent = described_class.new(
367
- ab_test_manager: ab_test_manager,
368
- evaluators: [base_evaluator]
369
- )
370
-
371
- # Access private method via send
372
- built_agent = agent.send(:build_agent, [])
373
- expect(built_agent).to be_a(DecisionAgent::Agent)
374
- end
375
-
376
- it "uses provided evaluators when not empty" do
377
- custom_evaluator = DecisionAgent::Evaluators::StaticEvaluator.new(
378
- decision: "reject",
379
- weight: 0.5
380
- )
381
- agent = described_class.new(
382
- ab_test_manager: ab_test_manager,
383
- evaluators: [base_evaluator]
384
- )
385
-
386
- built_agent = agent.send(:build_agent, [custom_evaluator])
387
- expect(built_agent).to be_a(DecisionAgent::Agent)
388
- end
389
- end
390
-
391
- describe "#build_evaluators_from_version" do
392
- it "falls back to base evaluators when content is not a hash" do
393
- invalid_version = { content: "not a hash" }
394
- allow(version_manager).to receive(:get_version).and_return(invalid_version)
395
- agent = described_class.new(
396
- ab_test_manager: ab_test_manager,
397
- version_manager: version_manager,
398
- evaluators: [base_evaluator]
399
- )
400
-
401
- evaluators = agent.send(:build_evaluators_from_version, invalid_version)
402
- expect(evaluators).to eq([base_evaluator])
403
- end
404
-
405
- it "falls back to base evaluators when content hash has no evaluators or rules" do
406
- invalid_version = { content: { other_key: "value" } }
407
- allow(version_manager).to receive(:get_version).and_return(invalid_version)
408
- agent = described_class.new(
409
- ab_test_manager: ab_test_manager,
410
- version_manager: version_manager,
411
- evaluators: [base_evaluator]
412
- )
413
-
414
- evaluators = agent.send(:build_evaluators_from_version, invalid_version)
415
- expect(evaluators).to eq([base_evaluator])
416
- end
417
- end
418
-
419
- describe "#build_evaluator_from_config" do
420
- it "builds JsonRuleEvaluator from config" do
421
- agent = described_class.new(
422
- ab_test_manager: ab_test_manager,
423
- version_manager: version_manager
424
- )
425
-
426
- config = {
427
- type: "json_rule",
428
- rules: {
429
- version: "1.0",
430
- ruleset: "test",
431
- rules: [
432
- {
433
- id: "rule_1",
434
- if: { field: "status", op: "eq", value: "active" },
435
- then: { decision: "approve", weight: 0.9 }
436
- }
437
- ]
438
- }
439
- }
440
-
441
- evaluator = agent.send(:build_evaluator_from_config, config)
442
- expect(evaluator).to be_a(DecisionAgent::Evaluators::JsonRuleEvaluator)
443
- end
444
-
445
- it "builds StaticEvaluator from config with default weight" do
446
- agent = described_class.new(
447
- ab_test_manager: ab_test_manager,
448
- version_manager: version_manager
449
- )
450
-
451
- config = {
452
- type: "static",
453
- decision: "approve",
454
- reason: "Test reason"
455
- # weight not provided, should default to 1.0
456
- }
457
-
458
- evaluator = agent.send(:build_evaluator_from_config, config)
459
- expect(evaluator).to be_a(DecisionAgent::Evaluators::StaticEvaluator)
460
- expect(evaluator.decision).to eq("approve")
461
- end
462
-
463
- it "builds StaticEvaluator from config with custom weight" do
464
- agent = described_class.new(
465
- ab_test_manager: ab_test_manager,
466
- version_manager: version_manager
467
- )
468
-
469
- config = {
470
- type: "static",
471
- decision: "reject",
472
- weight: 0.7,
473
- reason: "Custom weight"
474
- }
475
-
476
- evaluator = agent.send(:build_evaluator_from_config, config)
477
- expect(evaluator).to be_a(DecisionAgent::Evaluators::StaticEvaluator)
478
- expect(evaluator.decision).to eq("reject")
479
- end
480
- end
481
- end
@@ -1,64 +0,0 @@
1
- require "spec_helper"
2
- require_relative "../../../lib/decision_agent/ab_testing/storage/adapter"
3
-
4
- RSpec.describe DecisionAgent::ABTesting::Storage::Adapter do
5
- let(:adapter) { described_class.new }
6
-
7
- describe "#save_test" do
8
- it "raises NotImplementedError" do
9
- test = double("ABTest")
10
- expect { adapter.save_test(test) }.to raise_error(NotImplementedError, /must implement #save_test/)
11
- end
12
- end
13
-
14
- describe "#get_test" do
15
- it "raises NotImplementedError" do
16
- expect { adapter.get_test("test_id") }.to raise_error(NotImplementedError, /must implement #get_test/)
17
- end
18
- end
19
-
20
- describe "#update_test" do
21
- it "raises NotImplementedError" do
22
- expect { adapter.update_test("test_id", {}) }.to raise_error(NotImplementedError, /must implement #update_test/)
23
- end
24
- end
25
-
26
- describe "#list_tests" do
27
- it "raises NotImplementedError" do
28
- expect { adapter.list_tests }.to raise_error(NotImplementedError, /must implement #list_tests/)
29
- end
30
-
31
- it "raises NotImplementedError with status filter" do
32
- expect { adapter.list_tests(status: "active") }.to raise_error(NotImplementedError, /must implement #list_tests/)
33
- end
34
-
35
- it "raises NotImplementedError with limit" do
36
- expect { adapter.list_tests(limit: 10) }.to raise_error(NotImplementedError, /must implement #list_tests/)
37
- end
38
- end
39
-
40
- describe "#save_assignment" do
41
- it "raises NotImplementedError" do
42
- assignment = double("ABTestAssignment")
43
- expect { adapter.save_assignment(assignment) }.to raise_error(NotImplementedError, /must implement #save_assignment/)
44
- end
45
- end
46
-
47
- describe "#update_assignment" do
48
- it "raises NotImplementedError" do
49
- expect { adapter.update_assignment("assignment_id", {}) }.to raise_error(NotImplementedError, /must implement #update_assignment/)
50
- end
51
- end
52
-
53
- describe "#get_assignments" do
54
- it "raises NotImplementedError" do
55
- expect { adapter.get_assignments("test_id") }.to raise_error(NotImplementedError, /must implement #get_assignments/)
56
- end
57
- end
58
-
59
- describe "#delete_test" do
60
- it "raises NotImplementedError" do
61
- expect { adapter.delete_test("test_id") }.to raise_error(NotImplementedError, /must implement #delete_test/)
62
- end
63
- end
64
- end