Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/open_feature/sdk/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module SDK
# TODO: Write documentation
#
class Client
RESULT_TYPE = %i[boolean string number object].freeze
RESULT_TYPE = %i[boolean string number integer float object].freeze
SUFFIXES = %i[value details].freeze

attr_reader :metadata, :evaluation_context
Expand Down
12 changes: 10 additions & 2 deletions lib/open_feature/sdk/provider/in_memory_provider.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,15 @@ def fetch_string_value(flag_key:, default_value:, evaluation_context: nil)
end

def fetch_number_value(flag_key:, default_value:, evaluation_context: nil)
fetch_value(allowed_classes: [Integer, Float], flag_key:, default_value:, evaluation_context:)
fetch_value(allowed_classes: [Numeric], flag_key:, default_value:, evaluation_context:)
end

def fetch_integer_value(flag_key:, default_value:, evaluation_context: nil)
fetch_value(allowed_classes: [Integer], flag_key:, default_value:, evaluation_context:)
end

def fetch_float_value(flag_key:, default_value:, evaluation_context: nil)
fetch_value(allowed_classes: [Float], flag_key:, default_value:, evaluation_context:)
end

def fetch_object_value(flag_key:, default_value:, evaluation_context: nil)
Expand All @@ -52,7 +60,7 @@ def fetch_value(allowed_classes:, flag_key:, default_value:, evaluation_context:
return ResolutionDetails.new(value: default_value, error_code: ErrorCode::FLAG_NOT_FOUND, reason: Reason::ERROR)
end

if allowed_classes.include?(value.class)
if allowed_classes.any? { |klass| value.is_a?(klass) }
ResolutionDetails.new(value:, reason: Reason::STATIC)
else
ResolutionDetails.new(value: default_value, error_code: ErrorCode::TYPE_MISMATCH, reason: Reason::ERROR)
Expand Down
8 changes: 8 additions & 0 deletions lib/open_feature/sdk/provider/no_op_provider.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@ def fetch_number_value(flag_key:, default_value:, evaluation_context: nil)
no_op(default_value)
end

def fetch_integer_value(flag_key:, default_value:, evaluation_context: nil)
no_op(default_value)
end

def fetch_float_value(flag_key:, default_value:, evaluation_context: nil)
no_op(default_value)
end

def fetch_object_value(flag_key:, default_value:, evaluation_context: nil)
no_op(default_value)
end
Expand Down
14 changes: 11 additions & 3 deletions spec/open_feature/sdk/client_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,21 @@
expect(client).to respond_to(:fetch_number_value)
end

context "Condition 1.3.2 - The implementation language differentiates between floating-point numbers and integers." do
it do
expect(client.fetch_number_value(flag_key: flag_key, default_value: 4)).is_a?(Integer)
end

it do
expect(client.fetch_number_value(flag_key: flag_key, default_value: 95.5)).is_a?(Float)
end

context "Condition 1.3.3 - The implementation language differentiates between floating-point numbers and integers." do
it do
expect(client.fetch_number_value(flag_key: flag_key, default_value: 4)).is_a?(Integer)
expect(client.fetch_integer_value(flag_key: flag_key, default_value: 4)).is_a?(Integer)
end

it do
expect(client.fetch_number_value(flag_key: flag_key, default_value: 95.5)).is_a?(Float)
expect(client.fetch_float_value(flag_key: flag_key, default_value: 95.5)).is_a?(Float)
end
end
end
Expand Down
81 changes: 77 additions & 4 deletions spec/open_feature/sdk/provider/in_memory_provider_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
{
"bool" => true,
"str" => "testing",
"num" => 1,
"int" => 1,
"float" => 1.0,
"struct" => {"more" => "config"}
}
)
Expand Down Expand Up @@ -103,12 +104,18 @@
describe "#fetch_number_value" do
context "when flag is found" do
context "when type matches" do
it "returns value as static" do
fetched = provider.fetch_number_value(flag_key: "num", default_value: 0)
it "returns int as static" do
fetched = provider.fetch_number_value(flag_key: "int", default_value: 0)

expect(fetched.value).to eq(1)
expect(fetched.reason).to eq(OpenFeature::SDK::Provider::Reason::STATIC)
end
it "returns float as static" do
fetched = provider.fetch_number_value(flag_key: "float", default_value: 0.0)

expect(fetched.value).to eq(1.0)
expect(fetched.reason).to eq(OpenFeature::SDK::Provider::Reason::STATIC)
end
end

context "when type does not match" do
Expand All @@ -133,6 +140,72 @@
end
end

describe "#fetch_integer_value" do
context "when flag is found" do
context "when type matches" do
it "returns value as static" do
fetched = provider.fetch_integer_value(flag_key: "int", default_value: 0)

expect(fetched.value).to eq(1)
expect(fetched.reason).to eq(OpenFeature::SDK::Provider::Reason::STATIC)
end
end

context "when type does not match" do
it "returns default as type mismatch" do
fetched = provider.fetch_integer_value(flag_key: "float", default_value: 0)

expect(fetched.value).to eq(0)
expect(fetched.error_code).to eq(OpenFeature::SDK::Provider::ErrorCode::TYPE_MISMATCH)
expect(fetched.reason).to eq(OpenFeature::SDK::Provider::Reason::ERROR)
end
end
end

context "when flag is not found" do
it "returns default as flag not found" do
fetched = provider.fetch_number_value(flag_key: "not here", default_value: 0)

expect(fetched.value).to eq(0)
expect(fetched.error_code).to eq(OpenFeature::SDK::Provider::ErrorCode::FLAG_NOT_FOUND)
expect(fetched.reason).to eq(OpenFeature::SDK::Provider::Reason::ERROR)
end
end
end

describe "#fetch_integer_value" do
context "when flag is found" do
context "when type matches" do
it "returns value as static" do
fetched = provider.fetch_float_value(flag_key: "float", default_value: 0.0)

expect(fetched.value).to eq(1.0)
expect(fetched.reason).to eq(OpenFeature::SDK::Provider::Reason::STATIC)
end
end

context "when type does not match" do
it "returns default as type mismatch" do
fetched = provider.fetch_float_value(flag_key: "int", default_value: 0.0)

expect(fetched.value).to eq(0)
expect(fetched.error_code).to eq(OpenFeature::SDK::Provider::ErrorCode::TYPE_MISMATCH)
expect(fetched.reason).to eq(OpenFeature::SDK::Provider::Reason::ERROR)
end
end
end

context "when flag is not found" do
it "returns default as flag not found" do
fetched = provider.fetch_number_value(flag_key: "not here", default_value: 0)

expect(fetched.value).to eq(0)
expect(fetched.error_code).to eq(OpenFeature::SDK::Provider::ErrorCode::FLAG_NOT_FOUND)
expect(fetched.reason).to eq(OpenFeature::SDK::Provider::Reason::ERROR)
end
end
end

describe "#fetch_object_value" do
context "when flag is found" do
context "when type matches" do
Expand All @@ -146,7 +219,7 @@

context "when type does not match" do
it "returns default as type mismatch" do
fetched = provider.fetch_object_value(flag_key: "num", default_value: {})
fetched = provider.fetch_object_value(flag_key: "int", default_value: {})

expect(fetched.value).to eq({})
expect(fetched.error_code).to eq(OpenFeature::SDK::Provider::ErrorCode::TYPE_MISMATCH)
Expand Down