|
| 1 | +# frozen_string_literal: true |
| 2 | + |
| 3 | +# Before hook that adds context entries for "Before Hooks" level testing |
| 4 | +class ContextAddingBeforeHook |
| 5 | + include OpenFeature::SDK::Hooks::Hook |
| 6 | + |
| 7 | + attr_reader :context_entries |
| 8 | + |
| 9 | + def initialize |
| 10 | + @context_entries = {} |
| 11 | + end |
| 12 | + |
| 13 | + def add_entry(key, value) |
| 14 | + @context_entries[key] = value |
| 15 | + end |
| 16 | + |
| 17 | + def before(hook_context:, hints:) |
| 18 | + return nil if @context_entries.empty? |
| 19 | + |
| 20 | + OpenFeature::SDK::EvaluationContext.new(**@context_entries.transform_keys(&:to_sym)) |
| 21 | + end |
| 22 | +end |
| 23 | + |
| 24 | +Given("a stable provider with retrievable context is registered") do |
| 25 | + @capturing_provider = ContextCapturingProvider.new |
| 26 | + OpenFeature::SDK.set_provider_and_wait(@capturing_provider) |
| 27 | + @context_hook = ContextAddingBeforeHook.new |
| 28 | + @invocation_context_entries = {} |
| 29 | + @client_context_entries = {} |
| 30 | +end |
| 31 | + |
| 32 | +Given("A context entry with key {string} and value {string} is added to the {string} level") do |key, value, level| |
| 33 | + case level |
| 34 | + when "API" |
| 35 | + existing = OpenFeature::SDK.evaluation_context |
| 36 | + new_fields = existing ? existing.fields.merge(key => value) : {key => value} |
| 37 | + OpenFeature::SDK.configure do |config| |
| 38 | + config.evaluation_context = OpenFeature::SDK::EvaluationContext.new(**new_fields.transform_keys(&:to_sym)) |
| 39 | + end |
| 40 | + when "Transaction" |
| 41 | + propagator = OpenFeature::SDK.configuration.transaction_context_propagator |
| 42 | + unless propagator |
| 43 | + propagator = OpenFeature::SDK::ThreadLocalTransactionContextPropagator.new |
| 44 | + OpenFeature::SDK.configure do |config| |
| 45 | + config.transaction_context_propagator = propagator |
| 46 | + end |
| 47 | + end |
| 48 | + existing = propagator.get_transaction_context |
| 49 | + new_fields = existing ? existing.fields.merge(key => value) : {key => value} |
| 50 | + propagator.set_transaction_context( |
| 51 | + OpenFeature::SDK::EvaluationContext.new(**new_fields.transform_keys(&:to_sym)) |
| 52 | + ) |
| 53 | + when "Client" |
| 54 | + @client_context_entries[key] = value |
| 55 | + when "Invocation" |
| 56 | + @invocation_context_entries[key] = value |
| 57 | + when "Before Hooks" |
| 58 | + @context_hook.add_entry(key, value) |
| 59 | + end |
| 60 | +end |
| 61 | + |
| 62 | +When("Some flag was evaluated") do |
| 63 | + client_context = unless @client_context_entries.empty? |
| 64 | + OpenFeature::SDK::EvaluationContext.new(**@client_context_entries.transform_keys(&:to_sym)) |
| 65 | + end |
| 66 | + |
| 67 | + @client = OpenFeature::SDK.build_client(evaluation_context: client_context) |
| 68 | + @client.hooks = [@context_hook] |
| 69 | + |
| 70 | + invocation_context = unless @invocation_context_entries.empty? |
| 71 | + OpenFeature::SDK::EvaluationContext.new(**@invocation_context_entries.transform_keys(&:to_sym)) |
| 72 | + end |
| 73 | + |
| 74 | + @client.fetch_boolean_value( |
| 75 | + flag_key: "boolean-flag", |
| 76 | + default_value: false, |
| 77 | + evaluation_context: invocation_context |
| 78 | + ) |
| 79 | +end |
| 80 | + |
| 81 | +Then("The merged context contains an entry with key {string} and value {string}") do |key, value| |
| 82 | + merged = @capturing_provider.last_context |
| 83 | + expect(merged).not_to be_nil, "Expected merged context to be present" |
| 84 | + expect(merged.fields[key]).to eq(value), "Expected context[#{key}] = #{value}, got #{merged.fields[key].inspect}" |
| 85 | +end |
| 86 | + |
| 87 | +# -- Precedence table steps -- |
| 88 | + |
| 89 | +Given("A table with levels of increasing precedence") do |table| |
| 90 | + @precedence_levels = table.raw.flatten |
| 91 | +end |
| 92 | + |
| 93 | +Given("Context entries for each level from API level down to the {string} level, with key {string} and value {string}") do |target_level, key, value_template| |
| 94 | + @precedence_levels.each do |level| |
| 95 | + step_value = level |
| 96 | + step "A context entry with key \"#{key}\" and value \"#{step_value}\" is added to the \"#{level}\" level" |
| 97 | + break if level == target_level |
| 98 | + end |
| 99 | +end |
0 commit comments