Skip to content

Commit

Permalink
feat: allow local evaluation
Browse files Browse the repository at this point in the history
  • Loading branch information
duyhungtnn committed Oct 26, 2024
1 parent b3de67d commit f44c2ec
Show file tree
Hide file tree
Showing 45 changed files with 15,616 additions and 1,287 deletions.
16 changes: 15 additions & 1 deletion ava-test.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,19 @@ export default {
configFile: false,
},
},
files: ['__test/**/__tests__/*.js'],
files: [
'__test/**/__tests__/**/*.js',
'!__test/**/__tests__/utils/**',
'!__test/**/__tests__/testdata/**',
],
"typescript": {
"extensions": [
"ts",
"tsx"
],
"rewritePaths": {
"src/": "build/"
},
"compile": "tsc"
}
};
12 changes: 6 additions & 6 deletions e2e/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ test('Using a random string in the api key setting should not throw exception',
const user = { id: TARGETED_USER_ID, data: {} }
// The client can not load the evaluation, we will received the default value `true`
// Other SDK clients e2e test will expect the value is `false`
const result = await t.notThrowsAsync(bktClient.getBoolVariation(user, FEATURE_ID_BOOLEAN, true));
const result = await t.notThrowsAsync(bktClient.booleanVariation(user, FEATURE_ID_BOOLEAN, true));
t.true(result);

const bktClientImpl = bktClient as BKTClientImpl
Expand All @@ -48,11 +48,11 @@ test('altering featureTag should not affect api request', async (t) => {
}
const bktClient = initialize(config);
const user = { id: TARGETED_USER_ID, data: {} }
const result = await t.notThrowsAsync(bktClient.getBoolVariation(user, FEATURE_ID_BOOLEAN, false));
const result = await t.notThrowsAsync(bktClient.booleanVariation(user, FEATURE_ID_BOOLEAN, false));
t.true(result);
config.tag = "RANDOME"

const resultAfterAlterAPIKey = await t.notThrowsAsync(bktClient.getBoolVariation(user, FEATURE_ID_BOOLEAN, false));
const resultAfterAlterAPIKey = await t.notThrowsAsync(bktClient.booleanVariation(user, FEATURE_ID_BOOLEAN, false));
t.true(resultAfterAlterAPIKey);

bktClient.destroy()
Expand All @@ -67,11 +67,11 @@ test('Altering the api key should not affect api request', async (t) => {
}
const bktClient = initialize(config);
const user = { id: TARGETED_USER_ID, data: {} }
const result = await t.notThrowsAsync(bktClient.getBoolVariation(user, FEATURE_ID_BOOLEAN, false));
const result = await t.notThrowsAsync(bktClient.booleanVariation(user, FEATURE_ID_BOOLEAN, false));
t.true(result);
config.token = "RANDOME"

const resultAfterAlterAPIKey = await t.notThrowsAsync(bktClient.getBoolVariation(user, FEATURE_ID_BOOLEAN, false));
const resultAfterAlterAPIKey = await t.notThrowsAsync(bktClient.booleanVariation(user, FEATURE_ID_BOOLEAN, false));
t.true(resultAfterAlterAPIKey);

bktClient.destroy()
Expand All @@ -86,7 +86,7 @@ test('Using a random string in the featureTag setting should affect api request'
logger: new DefaultLogger("error")
});
const user = { id: TARGETED_USER_ID, data: {} }
const result = await t.notThrowsAsync(bktClient.getBoolVariation(user, FEATURE_ID_BOOLEAN, true));
const result = await t.notThrowsAsync(bktClient.booleanVariation(user, FEATURE_ID_BOOLEAN, true));
// The client can not load the evaluation, we will received the default value `true`
// Other SDK clients e2e test will expect the value is `false`
t.true(result);
Expand Down
75 changes: 69 additions & 6 deletions e2e/evaluations_defaut_strategy.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import anyTest, { TestFn } from 'ava';
import { Bucketeer, DefaultLogger, User, initialize } from '../lib';
import { HOST, TOKEN, FEATURE_TAG, TARGETED_USER_ID, FEATURE_ID_BOOLEAN, FEATURE_ID_STRING, FEATURE_ID_INT, FEATURE_ID_JSON, FEATURE_ID_FLOAT } from './constants/constants';
import { HOST, TOKEN, FEATURE_TAG, FEATURE_ID_BOOLEAN, FEATURE_ID_STRING, FEATURE_ID_INT, FEATURE_ID_JSON, FEATURE_ID_FLOAT } from './constants/constants';


const test = anyTest as TestFn<{ bktClient: Bucketeer; defaultUser: User }>;
Expand All @@ -19,23 +19,86 @@ test.beforeEach((t) => {

test('boolVariation', async (t) => {
const { bktClient, defaultUser } = t.context;
t.is(await bktClient.getBoolVariation(defaultUser, FEATURE_ID_BOOLEAN, false), true);
t.is(await bktClient.booleanVariation(defaultUser, FEATURE_ID_BOOLEAN, false), true);
t.deepEqual(
await bktClient.booleanVariationDetails(defaultUser, FEATURE_ID_BOOLEAN, false),
{
featureId: FEATURE_ID_BOOLEAN,
featureVersion: 5,
userId: defaultUser.id,
variationId: 'f948b6dd-c366-4828-8ee0-72edbe2c0eea',
variationName: 'variation 1',
variationValue: true,
reason: 'DEFAULT',
}
)
});

test('stringVariation', async (t) => {
const { bktClient, defaultUser } = t.context;
t.is(await bktClient.getStringVariation(defaultUser, FEATURE_ID_STRING, ''), 'value-1');
t.is(await bktClient.stringVariation(defaultUser, FEATURE_ID_STRING, ''), 'value-1');
t.deepEqual(
await bktClient.stringVariationDetails(defaultUser, FEATURE_ID_STRING, ''),
{
featureId: FEATURE_ID_STRING,
featureVersion: 4,
userId: defaultUser.id,
variationId: '16a9db43-dfba-485c-8300-8747af5caf61',
variationName: 'variation 1',
variationValue: 'value-1',
reason: 'DEFAULT',
}
)
});

test('numberVariation', async (t) => {
const { bktClient, defaultUser } = t.context;
t.is(await bktClient.getNumberVariation(defaultUser, FEATURE_ID_INT, 0), 10);
t.is(await bktClient.getNumberVariation(defaultUser, FEATURE_ID_FLOAT, 0.0), 2.1);
t.is(await bktClient.numberVariation(defaultUser, FEATURE_ID_INT, 0), 10);
t.deepEqual(
await bktClient.numberVariationDetails(defaultUser, FEATURE_ID_INT, 1),
{
featureId: FEATURE_ID_INT,
featureVersion: 5,
userId: defaultUser.id,
variationId: '935ac588-c3ef-4bc8-915b-666369cdcada',
variationName: 'variation 1',
variationValue: 10,
reason: 'DEFAULT',
}
)

t.is(await bktClient.numberVariation(defaultUser, FEATURE_ID_FLOAT, 0.0), 2.1);
t.deepEqual(
await bktClient.numberVariationDetails(defaultUser, FEATURE_ID_FLOAT, 1.1),
{
featureId: FEATURE_ID_FLOAT,
featureVersion: 5,
userId: defaultUser.id,
variationId: '0b04a309-31cd-471f-acf0-0ea662d16737',
variationName: 'variation 1',
variationValue: 2.1,
reason: 'DEFAULT',
}
)

});

test('jsonVariation', async (t) => {
test('objectVariation', async (t) => {
const { bktClient, defaultUser } = t.context;
t.deepEqual(await bktClient.getJsonVariation(defaultUser, FEATURE_ID_JSON, {}), { "str": "str1", "int": "int1" });
t.deepEqual(await bktClient.objectVariation(defaultUser, FEATURE_ID_JSON, {}), { "str": "str1", "int": "int1" });
t.deepEqual(
await bktClient.objectVariationDetails(defaultUser, FEATURE_ID_JSON, {}),
{
featureId: FEATURE_ID_JSON,
featureVersion: 5,
userId: defaultUser.id,
variationId: 'ff8299ed-80c9-4d30-9e92-a55750ad3ffb',
variationName: 'variation 1',
variationValue: { str: 'str1', int: 'int1' },
reason: 'DEFAULT',
}
)
});

test.afterEach(async (t) => {
Expand Down
73 changes: 68 additions & 5 deletions e2e/evaluations_targeting_strategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,86 @@ test.beforeEach((t) => {

test('boolVariation', async (t) => {
const { bktClient, targetedUser } = t.context;
t.is(await bktClient.getBoolVariation(targetedUser, FEATURE_ID_BOOLEAN, true), false);
t.is(await bktClient.booleanVariation(targetedUser, FEATURE_ID_BOOLEAN, true), false);
t.deepEqual(
await bktClient.booleanVariationDetails(targetedUser, FEATURE_ID_BOOLEAN, true),
{
featureId: FEATURE_ID_BOOLEAN,
featureVersion: 5,
userId: targetedUser.id,
variationId: '29f318b0-d770-48a5-8ae5-c1c692ed6cec',
variationName: 'variation 2',
variationValue: false,
reason: 'TARGET',
}
)
});

test('stringVariation', async (t) => {
const { bktClient, targetedUser } = t.context;
t.is(await bktClient.getStringVariation(targetedUser, FEATURE_ID_STRING, ''), 'value-2');
t.is(await bktClient.stringVariation(targetedUser, FEATURE_ID_STRING, ''), 'value-2');
t.deepEqual(
await bktClient.stringVariationDetails(targetedUser, FEATURE_ID_STRING, 'true'),
{
featureId: FEATURE_ID_STRING,
featureVersion: 4,
userId: targetedUser.id,
variationId: 'a3336346-931e-40f4-923a-603c642285d7',
variationName: 'variation 2',
variationValue: 'value-2',
reason: 'TARGET',
}
)
});

test('numberVariation', async (t) => {
const { bktClient, targetedUser } = t.context;
t.is(await bktClient.getNumberVariation(targetedUser, FEATURE_ID_INT, 0), 20);
t.is(await bktClient.getNumberVariation(targetedUser, FEATURE_ID_FLOAT, 0.0), 3.1);
t.is(await bktClient.numberVariation(targetedUser, FEATURE_ID_INT, 0), 20);
t.deepEqual(
await bktClient.numberVariationDetails(targetedUser, FEATURE_ID_INT, 99),
{
featureId: FEATURE_ID_INT,
featureVersion: 5,
userId: targetedUser.id,
variationId: '125380f8-5c18-4a80-b37d-a41331acf075',
variationName: 'variation 2',
variationValue: 20,
reason: 'TARGET',
}
)

t.is(await bktClient.numberVariation(targetedUser, FEATURE_ID_FLOAT, 0.0), 3.1);
t.deepEqual(
await bktClient.numberVariationDetails(targetedUser, FEATURE_ID_FLOAT, 99),
{
featureId: FEATURE_ID_FLOAT,
featureVersion: 5,
userId: targetedUser.id,
variationId: 'fdd0585b-dde4-4c2b-8f41-a1ca8f25d6a3',
variationName: 'variation 2',
variationValue: 3.1,
reason: 'TARGET',
}
)

});

test('jsonVariation', async (t) => {
test('objectVariation', async (t) => {
const { bktClient, targetedUser } = t.context;
t.deepEqual(await bktClient.getJsonVariation(targetedUser, FEATURE_ID_JSON, {}), { "str": "str2", "int": "int2" });
t.deepEqual(await bktClient.objectVariation(targetedUser, FEATURE_ID_JSON, {}), { "str": "str2", "int": "int2" });
t.deepEqual(
await bktClient.objectVariationDetails(targetedUser, FEATURE_ID_JSON, 99),
{
featureId: FEATURE_ID_JSON,
featureVersion: 5,
userId: targetedUser.id,
variationId: '636e08e5-7ecd-4c91-88f7-4443c8486767',
variationName: 'variation 2',
variationValue: { str: 'str2', int: 'int2' },
reason: 'TARGET',
}
)
});

test.afterEach(async (t) => {
Expand Down
15 changes: 8 additions & 7 deletions e2e/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ test.beforeEach((t) => {

test('goal event', async (t) => {
const { bktClient, targetedUser } = t.context;
t.is(await bktClient.getBoolVariation(targetedUser, FEATURE_ID_BOOLEAN, true), false);
t.is(await bktClient.booleanVariation(targetedUser, FEATURE_ID_BOOLEAN, true), false);
bktClient.track(targetedUser, GOAL_ID, GOAL_VALUE)
const bktClientImpl = bktClient as BKTClientImpl
const events = bktClientImpl.eventStore.getAll()
Expand All @@ -34,15 +34,16 @@ test('goal event', async (t) => {

test('default evaluation event', async (t) => {
const { bktClient, targetedUser } = t.context;
t.is(await bktClient.getBoolVariation(targetedUser, FEATURE_ID_BOOLEAN, true), false);
t.is(await bktClient.booleanVariation(targetedUser, FEATURE_ID_BOOLEAN, true), false);
t.deepEqual(await bktClient.getJsonVariation(targetedUser, FEATURE_ID_JSON, {}), { "str": "str2", "int": "int2" });
t.is(await bktClient.getNumberVariation(targetedUser, FEATURE_ID_INT, 0), 20);
t.is(await bktClient.getNumberVariation(targetedUser, FEATURE_ID_FLOAT, 0.0), 3.1);
t.is(await bktClient.getStringVariation(targetedUser, FEATURE_ID_STRING, ''), 'value-2');
t.deepEqual(await bktClient.objectVariation(targetedUser, FEATURE_ID_JSON, {}), { "str": "str2", "int": "int2" });
t.is(await bktClient.numberVariation(targetedUser, FEATURE_ID_INT, 0), 20);
t.is(await bktClient.numberVariation(targetedUser, FEATURE_ID_FLOAT, 0.0), 3.1);
t.is(await bktClient.stringVariation(targetedUser, FEATURE_ID_STRING, ''), 'value-2');
const bktClientImpl = bktClient as BKTClientImpl
const events = bktClientImpl.eventStore.getAll()
// (EvaluationEvent, Metrics Event - Latency, Metrics Event - Metrics Size) x 5
t.is(events.length, 15);
// (EvaluationEvent, Metrics Event - Latency, Metrics Event - Metrics Size) x 6
t.is(events.length, 18);
t.true(events.some((e) => (isEvaluationEvent(e.event))));
t.true(events.some((e) => (isMetricsEvent(e.event))));
});
Expand Down
2 changes: 1 addition & 1 deletion example/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ const html = ({ label }: { label: string }) => `

const controller = (_: express.Request, res: express.Response, next: express.NextFunction) => {
(async () => {
const label = await bucketeer.getStringVariation(
const label = await bucketeer.stringVariation(
{ id: 'uid', data: {} },
'node-server-debug',
'defaultValue',
Expand Down
Loading

0 comments on commit f44c2ec

Please sign in to comment.