diff --git a/README.md b/README.md index 4801173..17c0ae2 100644 --- a/README.md +++ b/README.md @@ -170,6 +170,21 @@ try { } ``` +To define the **default behavior** globally you can call the function `setUnknownFeatureState` + +```js +import { isEnabled, setEnabledFeatures, setUnknownFeatureState } from 'vue-feature-flipping' +setUnknownFeatureState(true); + +setEnabledFeatures(['FF1', 'FF3']) + +isEnabled('FF1') // returns true cause the flag is here +isEnabled('FF1', false) // returns true the flag is here +isEnabled('FF2') // returns true cause the default behavior is true du to the previous setUnknownFeatureState calls +isEnabled('FF2', false) // returns false cause the default behavior is passed as second argument + +``` + ### `not`: reversed rendering In some cases, we have to define a behavior when the feature is disabled. diff --git a/package-lock.json b/package-lock.json index 5527602..d873cb1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,6 +5,7 @@ "requires": true, "packages": { "": { + "name": "vue-feature-flipping", "version": "4.1.0", "license": "Apache-2.0", "devDependencies": { diff --git a/src/service.ts b/src/service.ts index cd4893a..0ffce01 100644 --- a/src/service.ts +++ b/src/service.ts @@ -1,10 +1,17 @@ import {ref, watch} from 'vue'; +const unknownFeatureState = ref(false); + const enabledFeatures = ref(null); -export function isEnabled(key: string, defaut = false) { +export function isEnabled(key: string, defaut?: boolean) { const keys = enabledFeatures.value - return keys === null ? defaut : keys.includes(key) + const defaultValue = defaut === undefined ? unknownFeatureState.value : defaut; + return keys === null ? defaultValue : keys.includes(key) +} + +export function setUnknownFeatureState(value: boolean) { + unknownFeatureState.value = value } export function setEnabledFeatures(features: string[] | null) { @@ -12,7 +19,7 @@ export function setEnabledFeatures(features: string[] | null) { } export function onFeaturesChanged(handler: () => void) { - return watch(enabledFeatures, (from, to) => { + return watch([enabledFeatures, unknownFeatureState], (from, to) => { handler() }) } diff --git a/tests/service.spec.ts b/tests/service.spec.ts index d307bdf..0e7556a 100644 --- a/tests/service.spec.ts +++ b/tests/service.spec.ts @@ -1,5 +1,5 @@ import {isEnabled, setEnabledFeatures} from '../src' -import {onFeaturesChanged} from "../src/service"; +import {onFeaturesChanged, setUnknownFeatureState} from "../src/service"; import {nextTick} from "vue"; describe('service', () => { @@ -23,6 +23,21 @@ describe('service', () => { }) }) + describe('Unknown flag should return unknownFeatureState value', () => { + beforeEach(() => setEnabledFeatures(null)) + + it('Should return "default" value', () => { + setUnknownFeatureState(true) + expect(isEnabled('KEY', true)).toEqual(true) + expect(isEnabled('KEY', false)).toEqual(false) + }) + + it('Default "default" value is "true"', () => { + setUnknownFeatureState(true) + expect(isEnabled('KEY')).toEqual(true) + }) + }) + describe('onFeaturesChanged', () => { it('Should call handler when features list updated', async () => { const handler = jest.fn() @@ -44,6 +59,24 @@ describe('service', () => { expect(handler).toHaveBeenCalledTimes(3) }) + it('Should call handler when unknownFeatureState updated', async () => { + setUnknownFeatureState(false) + const handler = jest.fn() + onFeaturesChanged(handler) + + setUnknownFeatureState(false) + await nextTick() + expect(handler).toHaveBeenCalledTimes(0) + + setUnknownFeatureState(true) + await nextTick() + expect(handler).toHaveBeenCalledTimes(1) + + setUnknownFeatureState(false) + await nextTick() + expect(handler).toHaveBeenCalledTimes(2) + }) + it('Should return function to unsubscribe', async () => { const handler = jest.fn() const unsubscriber = onFeaturesChanged(handler)