Added new unit tests for feature flags
This commit is contained in:
parent
0eed617866
commit
065e74024e
|
@ -6,7 +6,7 @@ import * as tenancy from "../tenancy"
|
||||||
* The env var is formatted as:
|
* The env var is formatted as:
|
||||||
* tenant1:feature1:feature2,tenant2:feature1
|
* tenant1:feature1:feature2,tenant2:feature1
|
||||||
*/
|
*/
|
||||||
function getFeatureFlags() {
|
export function buildFeatureFlags() {
|
||||||
if (!env.TENANT_FEATURE_FLAGS) {
|
if (!env.TENANT_FEATURE_FLAGS) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -27,8 +27,6 @@ function getFeatureFlags() {
|
||||||
return tenantFeatureFlags
|
return tenantFeatureFlags
|
||||||
}
|
}
|
||||||
|
|
||||||
const TENANT_FEATURE_FLAGS = getFeatureFlags()
|
|
||||||
|
|
||||||
export function isEnabled(featureFlag: string) {
|
export function isEnabled(featureFlag: string) {
|
||||||
const tenantId = tenancy.getTenantId()
|
const tenantId = tenancy.getTenantId()
|
||||||
const flags = getTenantFeatureFlags(tenantId)
|
const flags = getTenantFeatureFlags(tenantId)
|
||||||
|
@ -37,20 +35,23 @@ export function isEnabled(featureFlag: string) {
|
||||||
|
|
||||||
export function getTenantFeatureFlags(tenantId: string) {
|
export function getTenantFeatureFlags(tenantId: string) {
|
||||||
let flags: string[] = []
|
let flags: string[] = []
|
||||||
|
const envFlags = buildFeatureFlags()
|
||||||
if (TENANT_FEATURE_FLAGS) {
|
if (envFlags) {
|
||||||
const globalFlags = TENANT_FEATURE_FLAGS["*"]
|
const globalFlags = envFlags["*"]
|
||||||
const tenantFlags = TENANT_FEATURE_FLAGS[tenantId] || []
|
const tenantFlags = envFlags[tenantId] || []
|
||||||
|
|
||||||
// Explicitly exclude tenants from global features if required.
|
// Explicitly exclude tenants from global features if required.
|
||||||
// Prefix the tenant flag with '!'
|
// Prefix the tenant flag with '!'
|
||||||
const tenantOverrides = tenantFlags.reduce((acc: string[], flag) => {
|
const tenantOverrides = tenantFlags.reduce(
|
||||||
if (flag.startsWith("!")) {
|
(acc: string[], flag: string) => {
|
||||||
let stripped = flag.substring(1)
|
if (flag.startsWith("!")) {
|
||||||
acc.push(stripped)
|
let stripped = flag.substring(1)
|
||||||
}
|
acc.push(stripped)
|
||||||
return acc
|
}
|
||||||
}, [])
|
return acc
|
||||||
|
},
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
|
||||||
if (globalFlags) {
|
if (globalFlags) {
|
||||||
flags.push(...globalFlags)
|
flags.push(...globalFlags)
|
||||||
|
@ -72,4 +73,5 @@ export enum TenantFeatureFlag {
|
||||||
LICENSING = "LICENSING",
|
LICENSING = "LICENSING",
|
||||||
GOOGLE_SHEETS = "GOOGLE_SHEETS",
|
GOOGLE_SHEETS = "GOOGLE_SHEETS",
|
||||||
USER_GROUPS = "USER_GROUPS",
|
USER_GROUPS = "USER_GROUPS",
|
||||||
|
ONBOARDING_TOUR = "ONBOARDING_TOUR",
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
import {
|
||||||
|
TenantFeatureFlag,
|
||||||
|
buildFeatureFlags,
|
||||||
|
getTenantFeatureFlags,
|
||||||
|
} from "../"
|
||||||
|
import env from "../../environment"
|
||||||
|
|
||||||
|
const { ONBOARDING_TOUR, LICENSING, USER_GROUPS } = TenantFeatureFlag
|
||||||
|
|
||||||
|
describe("featureFlags", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
env._set("TENANT_FEATURE_FLAGS", "")
|
||||||
|
})
|
||||||
|
|
||||||
|
it("Should return no flags when the TENANT_FEATURE_FLAG is empty", async () => {
|
||||||
|
let features = buildFeatureFlags()
|
||||||
|
expect(features).toBeUndefined()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("Should generate a map of global and named tenant feature flags from the env value", async () => {
|
||||||
|
env._set(
|
||||||
|
"TENANT_FEATURE_FLAGS",
|
||||||
|
`*:${ONBOARDING_TOUR},tenant1:!${ONBOARDING_TOUR},tenant2:${USER_GROUPS},tenant1:${LICENSING}`
|
||||||
|
)
|
||||||
|
|
||||||
|
const parsedFlags: Record<string, string[]> = {
|
||||||
|
"*": [ONBOARDING_TOUR],
|
||||||
|
tenant1: [`!${ONBOARDING_TOUR}`, LICENSING],
|
||||||
|
tenant2: [USER_GROUPS],
|
||||||
|
}
|
||||||
|
|
||||||
|
let features = buildFeatureFlags()
|
||||||
|
|
||||||
|
expect(features).toBeDefined()
|
||||||
|
expect(features).toEqual(parsedFlags)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("Should add feature flag flag only to explicitly configured tenant", async () => {
|
||||||
|
env._set(
|
||||||
|
"TENANT_FEATURE_FLAGS",
|
||||||
|
`*:${LICENSING},*:${USER_GROUPS},tenant1:${ONBOARDING_TOUR}`
|
||||||
|
)
|
||||||
|
|
||||||
|
let tenant1Flags = getTenantFeatureFlags("tenant1")
|
||||||
|
let tenant2Flags = getTenantFeatureFlags("tenant2")
|
||||||
|
|
||||||
|
expect(tenant1Flags).toBeDefined()
|
||||||
|
expect(tenant1Flags).toEqual([LICENSING, USER_GROUPS, ONBOARDING_TOUR])
|
||||||
|
|
||||||
|
expect(tenant2Flags).toBeDefined()
|
||||||
|
expect(tenant2Flags).toEqual([LICENSING, USER_GROUPS])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("Should exclude tenant1 from global feature flag", async () => {
|
||||||
|
env._set(
|
||||||
|
"TENANT_FEATURE_FLAGS",
|
||||||
|
`*:${LICENSING},*:${ONBOARDING_TOUR},tenant1:!${ONBOARDING_TOUR}`
|
||||||
|
)
|
||||||
|
|
||||||
|
let tenant1Flags = getTenantFeatureFlags("tenant1")
|
||||||
|
let tenant2Flags = getTenantFeatureFlags("tenant2")
|
||||||
|
|
||||||
|
expect(tenant1Flags).toBeDefined()
|
||||||
|
expect(tenant1Flags).toEqual([LICENSING])
|
||||||
|
|
||||||
|
expect(tenant2Flags).toBeDefined()
|
||||||
|
expect(tenant2Flags).toEqual([LICENSING, ONBOARDING_TOUR])
|
||||||
|
})
|
||||||
|
|
||||||
|
it("Should explicitly add flags to configured tenants only", async () => {
|
||||||
|
env._set(
|
||||||
|
"TENANT_FEATURE_FLAGS",
|
||||||
|
`tenant1:${ONBOARDING_TOUR},tenant1:${LICENSING},tenant2:${LICENSING}`
|
||||||
|
)
|
||||||
|
|
||||||
|
let tenant1Flags = getTenantFeatureFlags("tenant1")
|
||||||
|
let tenant2Flags = getTenantFeatureFlags("tenant2")
|
||||||
|
|
||||||
|
expect(tenant1Flags).toBeDefined()
|
||||||
|
expect(tenant1Flags).toEqual([ONBOARDING_TOUR, LICENSING])
|
||||||
|
|
||||||
|
expect(tenant2Flags).toBeDefined()
|
||||||
|
expect(tenant2Flags).toEqual([LICENSING])
|
||||||
|
})
|
Loading…
Reference in New Issue