diff --git a/lib/open_feature/client.ex b/lib/open_feature/client.ex index 6b936e3..da8b9eb 100644 --- a/lib/open_feature/client.ex +++ b/lib/open_feature/client.ex @@ -258,7 +258,7 @@ defmodule OpenFeature.Client do } try do - before_hooks(all_hooks, hook_context, opts) + hook_context = before_hooks(all_hooks, hook_context, opts) short_circuit_if_not_ready(client) @@ -341,10 +341,19 @@ defmodule OpenFeature.Client do defp before_hooks(hooks, hook_context, opts) do hook_hints = Keyword.get(opts, :hook_hints, %{}) - Enum.each(hooks, fn - %Hook{before: nil} -> :ok - %Hook{before: before} -> before.(hook_context, hook_hints) - end) + context = + Enum.reduce(hooks, hook_context.context, fn + %Hook{before: nil}, context -> + context + + %Hook{before: before}, context -> + case before.(hook_context, hook_hints) do + data when is_map(data) -> Map.merge(context, data) + _other -> context + end + end) + + Map.put(hook_context, :context, context) end defp after_hooks(hooks, hook_context, evaluation_details, opts) do diff --git a/test/unit/open_feature/client_test.exs b/test/unit/open_feature/client_test.exs index 2c92778..05403e2 100644 --- a/test/unit/open_feature/client_test.exs +++ b/test/unit/open_feature/client_test.exs @@ -255,6 +255,37 @@ defmodule OpenFeature.ClientTest do assert_receive :hook_called end + test "context from before hook is carried to after hook", %{client: client} do + parent = self() + context = %{key: "value"} + key = "key" + default = true + + hook = %Hook{ + before: fn _hook_context, _hints -> + send(parent, :before_hook_called) + %{key: "other data"} + end, + after: fn hook_context, _details, _hints -> + assert_receive :provider_called + assert hook_context.context[:key] == "other data" + send(parent, :after_hook_called) + end + } + + expect(Provider, :resolve_value, 1, fn _provider, _type, _key, _default, _context -> + assert_receive :before_hook_called + send(parent, :provider_called) + {:ok, %ResolutionDetails{value: true}} + end) + + client = Client.add_hooks(client, [hook]) + + Client.get_boolean_value(client, key, default, context: context) + + assert_receive :after_hook_called + end + test "does not resolve value if an error occurs in before hooks", %{client: client} do parent = self() context = %{key: "value"}