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
7 changes: 5 additions & 2 deletions packages/react/src/declarative/FeatureFlag.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react';
import { useFlag } from '../evaluation';
import type { FlagQuery } from '../query';
import type { FlagValue, EvaluationDetails } from '@openfeature/core';
import { isEqual } from '../internal';

/**
* Default predicate function that checks if the expected value equals the actual flag value.
Expand All @@ -10,7 +11,7 @@ import type { FlagValue, EvaluationDetails } from '@openfeature/core';
* @returns {boolean} true if the values match, false otherwise
*/
function equals<T extends FlagValue>(expected: T, actual: EvaluationDetails<T>): boolean {
return expected === actual.value;
return isEqual(expected, actual.value);
}

/**
Expand Down Expand Up @@ -89,9 +90,11 @@ export function FeatureFlag<T extends FlagValue = FlagValue>({
} else if (match !== undefined) {
// Default behavior: check if match value equals flag value
shouldRender = equals(match, details.details as EvaluationDetails<T>);
} else {
} else if (details.type === 'boolean') {
// If no match value is provided, render if flag is truthy
shouldRender = Boolean(details.value);
} else {
shouldRender = false;
}

if (shouldRender) {
Expand Down
20 changes: 16 additions & 4 deletions packages/react/test/declarative.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,18 @@ describe('Feature Component', () => {
expect(screen.queryByText(childText)).toBeInTheDocument();
});

it('should not show a non-boolean feature flag without match', () => {
render(
<OpenFeatureProvider domain={EVALUATION}>
<FeatureFlag flagKey={STRING_FLAG_KEY} defaultValue={'hi'}>
<ChildComponent />
</FeatureFlag>
</OpenFeatureProvider>,
);

expect(screen.queryByText(childText)).not.toBeInTheDocument();
});

it('should fallback when provided', () => {
render(
<OpenFeatureProvider domain={EVALUATION}>
Expand Down Expand Up @@ -138,7 +150,7 @@ describe('Feature Component', () => {

it('should support function-based fallback with EvaluationDetails', () => {
const fallbackFunction = jest.fn((details: EvaluationDetails<boolean>) => <div>Fallback: {details.flagKey}</div>);

render(
<OpenFeatureProvider domain={EVALUATION}>
<FeatureFlag flagKey={MISSING_FLAG_KEY} defaultValue={false} fallback={fallbackFunction}>
Expand All @@ -158,7 +170,7 @@ describe('Feature Component', () => {
const fallbackFunction = jest.fn((details: EvaluationDetails<boolean>) => {
return <div>Flag: {details.flagKey}, Value: {String(details.value)}, Reason: {details.reason}</div>;
});

render(
<OpenFeatureProvider domain={EVALUATION}>
<FeatureFlag flagKey={MISSING_FLAG_KEY} defaultValue={false} fallback={fallbackFunction}>
Expand All @@ -178,9 +190,9 @@ describe('Feature Component', () => {
// Create a provider that will cause an error
const errorProvider = new InMemoryProvider({});
OpenFeature.setProvider('error-test', errorProvider);

const fallbackFunction = jest.fn((details: EvaluationDetails<boolean>) => <div>Error fallback: {details.reason}</div>);

render(
<OpenFeatureProvider domain="error-test">
<FeatureFlag flagKey={MISSING_FLAG_KEY} defaultValue={false} fallback={fallbackFunction}>
Expand Down