Skip to content

Commit

Permalink
fix evaluation: FeatureFlag.enabled defaults to false (#11)
Browse files Browse the repository at this point in the history
  • Loading branch information
Eskibear authored May 23, 2024
1 parent 382dd86 commit c541c29
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 2 deletions.
13 changes: 11 additions & 2 deletions src/featureManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,11 @@ export class FeatureManager {
return false;
}

if (featureFlag.enabled === false) {
// If the feature is explicitly disabled, then it is disabled.
// Ensure that the feature flag is in the correct format. Feature providers should validate the feature flags, but we do it here as a safeguard.
validateFeatureFlagFormat(featureFlag);

if (featureFlag.enabled !== true) {
// If the feature is not explicitly enabled, then it is disabled by default.
return false;
}

Expand Down Expand Up @@ -77,3 +80,9 @@ export class FeatureManager {
interface FeatureManagerOptions {
customFilters?: IFeatureFilter[];
}

function validateFeatureFlagFormat(featureFlag: any): void {
if (featureFlag.enabled !== undefined && typeof featureFlag.enabled !== "boolean") {
throw new Error(`Feature flag ${featureFlag.id} has an invalid 'enabled' value.`);
}
}
70 changes: 70 additions & 0 deletions test/noFilters.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import * as chai from "chai";
import * as chaiAsPromised from "chai-as-promised";
chai.use(chaiAsPromised);
const expect = chai.expect;

import { FeatureManager, ConfigurationObjectFeatureFlagProvider } from "./exportedApi";

const featureFlagsDataObject = {
"feature_management": {
"feature_flags": [
{
"id": "BooleanTrue",
"description": "A feature flag with no Filters, that returns true.",
"enabled": true,
"conditions": {
"client_filters": []
}
},
{
"id": "BooleanFalse",
"description": "A feature flag with no Filters, that returns false.",
"enabled": false,
"conditions": {
"client_filters": []
}
},
{
"id": "InvalidEnabled",
"description": "A feature flag with an invalid 'enabled' value, that throws an exception.",
"enabled": "invalid",
"conditions": {
"client_filters": []
}
},
{
"id": "Minimal",
"enabled": true
},
{
"id": "NoEnabled"
},
{
"id": "EmptyConditions",
"description": "A feature flag with no values in conditions, that returns true.",
"enabled": true,
"conditions": {
}
}
]
}
};

describe("feature flags with no filters", () => {
it("should validate feature flags without filters", () => {
const provider = new ConfigurationObjectFeatureFlagProvider(featureFlagsDataObject);
const featureManager = new FeatureManager(provider);

return Promise.all([
expect(featureManager.isEnabled("BooleanTrue")).eventually.eq(true),
expect(featureManager.isEnabled("BooleanFalse")).eventually.eq(false),
expect(featureManager.isEnabled("InvalidEnabled")).eventually.rejectedWith("Feature flag InvalidEnabled has an invalid 'enabled' value."),
expect(featureManager.isEnabled("Minimal")).eventually.eq(true),
expect(featureManager.isEnabled("NoEnabled")).eventually.eq(false),
expect(featureManager.isEnabled("EmptyConditions")).eventually.eq(true)
]);
});
});

0 comments on commit c541c29

Please sign in to comment.