Skip to content

Commit 07a6def

Browse files
committed
feat: add capability to read feature flags on frontend
1 parent 34f53ad commit 07a6def

File tree

2 files changed

+63
-0
lines changed

2 files changed

+63
-0
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { Config } from 'src/libs/config'
2+
import { getAllFeatureFlags, getFeatureFlag } from 'src/libs/ajax/FeatureFlag'
3+
4+
describe('FeatureFlag ajax', () => {
5+
let fetchStub: ReturnType<typeof cy.stub>
6+
7+
beforeEach(() => {
8+
cy.initApplicationConfig()
9+
cy.stub(Config, 'getApiUrl').resolves('')
10+
cy.window().then((win) => {
11+
fetchStub = cy.stub(win, 'fetch')
12+
})
13+
})
14+
15+
afterEach(() => {
16+
cy.window().then(() => {
17+
fetchStub.restore()
18+
})
19+
})
20+
21+
it('getAllFeatureFlags returns a map of flags', () => {
22+
const response = { featureAlpha: 'on', featureBeta: 'off' }
23+
cy.window().then((win) => {
24+
fetchStub.resolves(new win.Response(JSON.stringify(response), { status: 200, headers: { 'content-type': 'application/json' } }))
25+
cy.wrap(getAllFeatureFlags()).should('deep.equal', response)
26+
})
27+
})
28+
29+
it('getFeatureFlag returns the per-key value when available', () => {
30+
cy.window().then((win) => {
31+
fetchStub.resolves(new win.Response(JSON.stringify('enabled'), { status: 200, headers: { 'content-type': 'application/json' } }))
32+
cy.wrap(getFeatureFlag('someFlag')).should('equal', 'enabled')
33+
})
34+
})
35+
36+
it('getFeatureFlag returns undefined when per-key endpoint errors', () => {
37+
cy.window().then(() => {
38+
fetchStub.rejects(new Error('Not found'))
39+
cy.wrap(getFeatureFlag('missingFlag')).should('be.undefined')
40+
})
41+
})
42+
})

src/libs/ajax/FeatureFlag.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { Config } from 'src/libs/config'
2+
import { fetchGet } from 'src/libs/ajax/fetchAdapter'
3+
4+
type FeatureFlagValue = string
5+
6+
export async function getAllFeatureFlags(): Promise<Record<string, FeatureFlagValue> | FeatureFlagValue[]> {
7+
const url = `${await Config.getApiUrl()}/api/featureFlags`
8+
const res = await fetchGet<Record<string, FeatureFlagValue> | FeatureFlagValue[]>(url, Config.authOpts())
9+
return res.data
10+
}
11+
12+
export async function getFeatureFlag(key: string): Promise<FeatureFlagValue | undefined> {
13+
const url = `${await Config.getApiUrl()}/api/featureFlags/${encodeURIComponent(key)}`
14+
try {
15+
const res = await fetchGet<FeatureFlagValue>(url, Config.authOpts())
16+
return res.data
17+
}
18+
catch {
19+
return undefined
20+
}
21+
}

0 commit comments

Comments
 (0)