Skip to content

Commit

Permalink
#201 (feat): added envId to the storage key and added property to cac…
Browse files Browse the repository at this point in the history
…heOptions to customize the key
  • Loading branch information
oluizcarvalho committed Sep 5, 2024
1 parent 69209a3 commit a014785
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 23 deletions.
20 changes: 13 additions & 7 deletions flagsmith-core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,10 @@ type RequestOptions = {
}

let AsyncStorage: AsyncStorageType = null;
const FLAGSMITH_KEY = "BULLET_TRAIN_DB";
const FLAGSMITH_EVENT = "BULLET_TRAIN_EVENT";
const DEFAULT_FLAGSMITH_KEY = "BULLET_TRAIN_DB";
const DEFAULT_FLAGSMITH_EVENT = "BULLET_TRAIN_EVENT";
let FlagsmithKey = DEFAULT_FLAGSMITH_KEY;
let FlagsmithEvent = DEFAULT_FLAGSMITH_EVENT;
const defaultAPI = 'https://edge.api.flagsmith.com/api/v1/';
let eventSource: typeof EventSource;
const initError = function(caller: string) {
Expand Down Expand Up @@ -320,6 +322,10 @@ const Flagsmith = class {
this.ticks = 10000;
this.timer = this.enableLogs ? new Date().valueOf() : null;
this.cacheFlags = typeof AsyncStorage !== 'undefined' && !!cacheFlags;

FlagsmithKey = cacheOptions?.storageKey || DEFAULT_FLAGSMITH_KEY + "_" + environmentID;
FlagsmithEvent = DEFAULT_FLAGSMITH_EVENT + "_" + environmentID;

if (_AsyncStorage) {
AsyncStorage = _AsyncStorage;
}
Expand Down Expand Up @@ -360,7 +366,7 @@ const Flagsmith = class {
}

if (AsyncStorage && this.canUseStorage) {
AsyncStorage.getItem(FLAGSMITH_EVENT)
AsyncStorage.getItem(FlagsmithEvent)
.then((res)=>{
try {
this.evaluationEvent = JSON.parse(res!) || {}
Expand All @@ -377,7 +383,7 @@ const Flagsmith = class {
}

if (AsyncStorage && this.canUseStorage) {
AsyncStorage.getItem(FLAGSMITH_EVENT, (err, res) => {
AsyncStorage.getItem(FlagsmithEvent, (err, res) => {
if (res) {
const json = JSON.parse(res);
if (json[this.environmentID]) {
Expand Down Expand Up @@ -469,7 +475,7 @@ const Flagsmith = class {
}
};
try {
const res = AsyncStorage.getItemSync? AsyncStorage.getItemSync(FLAGSMITH_KEY) : await AsyncStorage.getItem(FLAGSMITH_KEY);
const res = AsyncStorage.getItemSync? AsyncStorage.getItemSync(FlagsmithKey) : await AsyncStorage.getItem(FlagsmithKey);
await onRetrievedStorage(null, res)
} catch (e) {}
}
Expand Down Expand Up @@ -685,7 +691,7 @@ const Flagsmith = class {
this.ts = new Date().valueOf();
const state = JSON.stringify(this.getState());
this.log('Setting storage', state);
AsyncStorage!.setItem(FLAGSMITH_KEY, state);
AsyncStorage!.setItem(FlagsmithKey, state);
}
}

Expand Down Expand Up @@ -749,7 +755,7 @@ const Flagsmith = class {
private updateEventStorage() {
if (this.enableAnalytics) {
const events = JSON.stringify(this.getState().evaluationEvent);
AsyncStorage!.setItem(FLAGSMITH_EVENT, events);
AsyncStorage!.setItem(FlagsmithEvent, events);
}
}

Expand Down
36 changes: 25 additions & 11 deletions test/cache.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Sample test
import {
defaultState,
defaultStateAlt,
defaultStateAlt, FLAGSMITH_KEY,
getFlagsmith,
getStateToCheck,
identityState,
Expand Down Expand Up @@ -32,7 +32,21 @@ describe('Cache', () => {
onChange,
});
await flagsmith.init(initConfig);
const cache = await AsyncStorage.getItem('BULLET_TRAIN_DB');
const cache = await AsyncStorage.getItem(FLAGSMITH_KEY);
expect(getStateToCheck(JSON.parse(`${cache}`))).toEqual(defaultState);
});
test('should set cache after init with custom key', async () => {
const onChange = jest.fn();
const customKey = 'custom_key';
const { flagsmith, initConfig, AsyncStorage, mockFetch } = getFlagsmith({
cacheFlags: true,
cacheOptions: {
storageKey: customKey,
},
onChange,
});
await flagsmith.init(initConfig);
const cache = await AsyncStorage.getItem(customKey);
expect(getStateToCheck(JSON.parse(`${cache}`))).toEqual(defaultState);
});
test('should call onChange with cache then eventually with an API response', async () => {
Expand All @@ -52,7 +66,7 @@ describe('Cache', () => {
cacheFlags: true,
onChange,
});
await AsyncStorage.setItem('BULLET_TRAIN_DB', JSON.stringify(defaultStateAlt));
await AsyncStorage.setItem(FLAGSMITH_KEY, JSON.stringify(defaultStateAlt));
await flagsmith.init(initConfig);

// Flags retrieved from cache
Expand Down Expand Up @@ -85,7 +99,7 @@ describe('Cache', () => {
identity: testIdentity,
onChange,
});
await AsyncStorage.setItem('BULLET_TRAIN_DB', JSON.stringify({
await AsyncStorage.setItem(FLAGSMITH_KEY, JSON.stringify({
...defaultStateAlt,
identity: 'bad_identity',
}));
Expand All @@ -101,7 +115,7 @@ describe('Cache', () => {
onChange,
cacheOptions: { ttl: 1 },
});
await AsyncStorage.setItem('BULLET_TRAIN_DB', JSON.stringify({
await AsyncStorage.setItem(FLAGSMITH_KEY, JSON.stringify({
...defaultStateAlt,
ts: new Date().valueOf() - 100,
}));
Expand All @@ -119,7 +133,7 @@ describe('Cache', () => {
onChange,
cacheOptions: { ttl: 1000 },
});
await AsyncStorage.setItem('BULLET_TRAIN_DB', JSON.stringify({
await AsyncStorage.setItem(FLAGSMITH_KEY, JSON.stringify({
...defaultStateAlt,
ts: new Date().valueOf(),
}));
Expand All @@ -136,7 +150,7 @@ describe('Cache', () => {
cacheFlags: false,
onChange,
});
await AsyncStorage.setItem('BULLET_TRAIN_DB', JSON.stringify({
await AsyncStorage.setItem(FLAGSMITH_KEY, JSON.stringify({
...defaultStateAlt,
ts: new Date().valueOf(),
}));
Expand All @@ -154,7 +168,7 @@ describe('Cache', () => {
onChange,
cacheOptions: { ttl: 1000, skipAPI: true },
});
await AsyncStorage.setItem('BULLET_TRAIN_DB', JSON.stringify({
await AsyncStorage.setItem(FLAGSMITH_KEY, JSON.stringify({
...defaultStateAlt,
ts: new Date().valueOf(),
}));
Expand All @@ -172,7 +186,7 @@ describe('Cache', () => {
cacheFlags: true,
preventFetch: true,
});
await AsyncStorage.setItem('BULLET_TRAIN_DB', JSON.stringify({
await AsyncStorage.setItem(FLAGSMITH_KEY, JSON.stringify({
...defaultState,
}));
await flagsmith.init(initConfig);
Expand Down Expand Up @@ -218,7 +232,7 @@ describe('Cache', () => {
preventFetch: true,
defaultFlags: defaultState.flags,
});
await AsyncStorage.setItem('BULLET_TRAIN_DB', JSON.stringify({
await AsyncStorage.setItem(FLAGSMITH_KEY, JSON.stringify({
...defaultState,
}));
await flagsmith.init(initConfig);
Expand Down Expand Up @@ -264,7 +278,7 @@ describe('Cache', () => {
preventFetch: true,
});
const storage = new SyncStorageMock();
await storage.setItem('BULLET_TRAIN_DB', JSON.stringify({
await storage.setItem(FLAGSMITH_KEY, JSON.stringify({
...defaultState,
}));
flagsmith.init({
Expand Down
4 changes: 2 additions & 2 deletions test/default-flags.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Sample test
import { defaultState, defaultStateAlt, getFlagsmith, getStateToCheck } from './test-constants';
import { defaultState, defaultStateAlt, FLAGSMITH_KEY, getFlagsmith, getStateToCheck } from './test-constants';
import { IFlags } from '../types';

describe('Default Flags', () => {
Expand Down Expand Up @@ -51,7 +51,7 @@ describe('Default Flags', () => {
cacheFlags: true,
defaultFlags: {...defaultFlags, ...itemsToRemove},
});
await AsyncStorage.setItem('BULLET_TRAIN_DB', JSON.stringify({
await AsyncStorage.setItem(FLAGSMITH_KEY, JSON.stringify({
...defaultState,
flags: {
...defaultFlags,
Expand Down
39 changes: 37 additions & 2 deletions test/react.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import React, { FC } from 'react';
import { render, screen, waitFor } from '@testing-library/react';
import { FlagsmithProvider, useFlags, useFlagsmithLoading } from '../lib/flagsmith/react';
import { defaultState, environmentID, getFlagsmith, identityState, testIdentity } from './test-constants';
import {
defaultState,
FLAGSMITH_KEY,
getFlagsmith,
identityState,
testIdentity,
} from './test-constants';
import removeIds from './test-utils/remove-ids';
const FlagsmithPage: FC<any> = () => {
const flags = useFlags(Object.keys(defaultState.flags))
Expand All @@ -18,6 +24,7 @@ const FlagsmithPage: FC<any> = () => {
);
};


export default FlagsmithPage;
describe('FlagsmithProvider', () => {
it('renders without crashing', () => {
Expand Down Expand Up @@ -84,7 +91,34 @@ describe('FlagsmithProvider', () => {
preventFetch: true,
defaultFlags: defaultState.flags
});
await AsyncStorage.setItem("BULLET_TRAIN_DB", JSON.stringify({
await AsyncStorage.setItem(FLAGSMITH_KEY, JSON.stringify({
...defaultState
}) )
render(
<FlagsmithProvider flagsmith={flagsmith} options={initConfig}>
<FlagsmithPage/>
</FlagsmithProvider>
);

await waitFor(() => {
expect(JSON.parse(screen.getByTestId("loading-state").innerHTML)).toEqual({"isLoading":false,"isFetching":false,"error":null,"source":"CACHE"});
expect(JSON.parse(screen.getByTestId("flags").innerHTML)).toEqual(removeIds(defaultState.flags));
});
});

it('renders cached flags by custom key', async () => {
const customKey = 'custom_key';
const onChange = jest.fn();
const { flagsmith, initConfig, AsyncStorage } = getFlagsmith({
onChange,
cacheFlags: true,
preventFetch: true,
defaultFlags: defaultState.flags,
cacheOptions: {
storageKey: customKey,
},
});
await AsyncStorage.setItem(customKey, JSON.stringify({
...defaultState
}) )
render(
Expand All @@ -98,6 +132,7 @@ describe('FlagsmithProvider', () => {
expect(JSON.parse(screen.getByTestId("flags").innerHTML)).toEqual(removeIds(defaultState.flags));
});
});

it('renders default flags', async () => {

const onChange = jest.fn();
Expand Down
2 changes: 1 addition & 1 deletion test/test-constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import MockAsyncStorage from './mocks/async-storage-mock';
import { createFlagsmithInstance } from '../lib/flagsmith';
import fetch from 'isomorphic-unfetch';
export const environmentID = 'QjgYur4LQTwe5HpvbvhpzK'; // Flagsmith Demo Projects

export const FLAGSMITH_KEY = 'BULLET_TRAIN_DB' + "_" + environmentID;
export const defaultState = {
api: 'https://edge.api.flagsmith.com/api/v1/',
environmentID,
Expand Down
1 change: 1 addition & 0 deletions types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export interface IState<F extends string = string, T extends string = string> {
declare type ICacheOptions = {
ttl?: number;
skipAPI?: boolean;
storageKey?: string;
};

export declare type IDatadogRum = {
Expand Down

0 comments on commit a014785

Please sign in to comment.