|
81 | 81 | end |
82 | 82 | end |
83 | 83 |
|
| 84 | + context "Requirement 4.1.5" do |
| 85 | + specify "Hook context MUST provide a mechanism for hook instances to store and retrieve per-hook data" do |
| 86 | + data_across_stages = {} |
| 87 | + |
| 88 | + hook = Class.new do |
| 89 | + include OpenFeature::SDK::Hooks::Hook |
| 90 | + |
| 91 | + define_method(:before) do |hook_context:, hints:| |
| 92 | + hook_context.hook_data_for(self)["my_key"] = "set_in_before" |
| 93 | + nil |
| 94 | + end |
| 95 | + |
| 96 | + define_method(:after) do |hook_context:, evaluation_details:, hints:| |
| 97 | + data_across_stages[:after_value] = hook_context.hook_data_for(self)["my_key"] |
| 98 | + end |
| 99 | + |
| 100 | + define_method(:finally) do |hook_context:, evaluation_details:, hints:| |
| 101 | + data_across_stages[:finally_value] = hook_context.hook_data_for(self)["my_key"] |
| 102 | + end |
| 103 | + end.new |
| 104 | + |
| 105 | + client = OpenFeature::SDK.build_client |
| 106 | + client.fetch_boolean_value(flag_key: "flag-1", default_value: false, hooks: [hook]) |
| 107 | + |
| 108 | + expect(data_across_stages[:after_value]).to eq("set_in_before") |
| 109 | + expect(data_across_stages[:finally_value]).to eq("set_in_before") |
| 110 | + end |
| 111 | + |
| 112 | + specify "Hook data MUST be isolated between different hook instances" do |
| 113 | + hook_a_data = {} |
| 114 | + hook_b_data = {} |
| 115 | + |
| 116 | + hook_a = Class.new do |
| 117 | + include OpenFeature::SDK::Hooks::Hook |
| 118 | + |
| 119 | + define_method(:before) do |hook_context:, hints:| |
| 120 | + hook_context.hook_data_for(self)["owner"] = "hook_a" |
| 121 | + nil |
| 122 | + end |
| 123 | + |
| 124 | + define_method(:after) do |hook_context:, evaluation_details:, hints:| |
| 125 | + hook_a_data[:owner] = hook_context.hook_data_for(self)["owner"] |
| 126 | + end |
| 127 | + end.new |
| 128 | + |
| 129 | + hook_b = Class.new do |
| 130 | + include OpenFeature::SDK::Hooks::Hook |
| 131 | + |
| 132 | + define_method(:before) do |hook_context:, hints:| |
| 133 | + hook_context.hook_data_for(self)["owner"] = "hook_b" |
| 134 | + nil |
| 135 | + end |
| 136 | + |
| 137 | + define_method(:after) do |hook_context:, evaluation_details:, hints:| |
| 138 | + hook_b_data[:owner] = hook_context.hook_data_for(self)["owner"] |
| 139 | + end |
| 140 | + end.new |
| 141 | + |
| 142 | + client = OpenFeature::SDK.build_client |
| 143 | + client.fetch_boolean_value(flag_key: "flag-1", default_value: false, hooks: [hook_a, hook_b]) |
| 144 | + |
| 145 | + expect(hook_a_data[:owner]).to eq("hook_a") |
| 146 | + expect(hook_b_data[:owner]).to eq("hook_b") |
| 147 | + end |
| 148 | + end |
| 149 | + |
84 | 150 | context "Requirement 4.1.4" do |
85 | 151 | specify "evaluation context MUST be mutable" do |
86 | 152 | captured_context = nil |
@@ -246,6 +312,51 @@ def before(hook_context:, hints:) |
246 | 312 | expect(finally_count).to eq(2) |
247 | 313 | end |
248 | 314 | end |
| 315 | + |
| 316 | + context "Requirement 4.3.8" do |
| 317 | + specify "On success, finally hook receives evaluation details with the resolved value" do |
| 318 | + captured_details = nil |
| 319 | + |
| 320 | + hook = Class.new do |
| 321 | + include OpenFeature::SDK::Hooks::Hook |
| 322 | + |
| 323 | + define_method(:finally) do |hook_context:, evaluation_details:, hints:| |
| 324 | + captured_details = evaluation_details |
| 325 | + end |
| 326 | + end.new |
| 327 | + |
| 328 | + client = OpenFeature::SDK.build_client |
| 329 | + client.fetch_boolean_value(flag_key: "flag-1", default_value: false, hooks: [hook]) |
| 330 | + |
| 331 | + expect(captured_details).not_to be_nil |
| 332 | + expect(captured_details.value).to eq(true) |
| 333 | + expect(captured_details.flag_key).to eq("flag-1") |
| 334 | + end |
| 335 | + |
| 336 | + specify "On error, finally hook receives evaluation details with default value and error info" do |
| 337 | + captured_details = nil |
| 338 | + |
| 339 | + hook = Class.new do |
| 340 | + include OpenFeature::SDK::Hooks::Hook |
| 341 | + |
| 342 | + define_method(:finally) do |hook_context:, evaluation_details:, hints:| |
| 343 | + captured_details = evaluation_details |
| 344 | + end |
| 345 | + end.new |
| 346 | + |
| 347 | + allow(provider).to receive(:fetch_boolean_value).and_raise("provider error") |
| 348 | + |
| 349 | + client = OpenFeature::SDK.build_client |
| 350 | + client.fetch_boolean_value(flag_key: "flag-1", default_value: false, hooks: [hook]) |
| 351 | + |
| 352 | + expect(captured_details).not_to be_nil |
| 353 | + expect(captured_details.value).to eq(false) |
| 354 | + expect(captured_details.flag_key).to eq("flag-1") |
| 355 | + expect(captured_details.error_code).to eq(OpenFeature::SDK::Provider::ErrorCode::GENERAL) |
| 356 | + expect(captured_details.reason).to eq(OpenFeature::SDK::Provider::Reason::ERROR) |
| 357 | + expect(captured_details.error_message).to eq("provider error") |
| 358 | + end |
| 359 | + end |
249 | 360 | end |
250 | 361 |
|
251 | 362 | context "4.4 - Hook Execution" do |
|
0 commit comments