Skip to content

Commit 5d2b695

Browse files
committed
MOAR tests
1 parent 247213c commit 5d2b695

File tree

2 files changed

+244
-8
lines changed

2 files changed

+244
-8
lines changed

src/client/eppo-client.spec.ts

Lines changed: 244 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
} from '../../test/testHelpers';
1616
import { IAssignmentLogger } from '../assignment-logger';
1717
import { AssignmentCache } from '../cache/abstract-assignment-cache';
18+
import { ConfigurationManager } from '../configuration-store/configuration-manager';
1819
import { IConfigurationStore } from '../configuration-store/configuration-store';
1920
import { MemoryOnlyConfigurationStore } from '../configuration-store/memory.store';
2021
import {
@@ -24,7 +25,15 @@ import {
2425
} from '../configuration-wire/configuration-wire-types';
2526
import { MAX_EVENT_QUEUE_SIZE, DEFAULT_POLL_INTERVAL_MS, POLL_JITTER_PCT } from '../constants';
2627
import { decodePrecomputedFlag } from '../decoding';
27-
import { Flag, ObfuscatedFlag, VariationType, FormatEnum, Variation } from '../interfaces';
28+
import {
29+
Flag,
30+
ObfuscatedFlag,
31+
VariationType,
32+
FormatEnum,
33+
Variation,
34+
BanditVariation,
35+
BanditParameters,
36+
} from '../interfaces';
2837
import { getMD5Hash } from '../obfuscation';
2938
import { AttributeType } from '../types';
3039

@@ -1191,3 +1200,237 @@ describe('EppoClient E2E test', () => {
11911200
});
11921201
});
11931202
});
1203+
1204+
describe('EppoClient ConfigurationManager Integration', () => {
1205+
let client: EppoClient;
1206+
let flagStore: MemoryOnlyConfigurationStore<Flag | ObfuscatedFlag>;
1207+
let banditVariationStore: MemoryOnlyConfigurationStore<BanditVariation[]>;
1208+
let banditModelStore: MemoryOnlyConfigurationStore<BanditParameters>;
1209+
1210+
// Sample flag with correct shape
1211+
const testFlag: Flag = {
1212+
key: 'test-flag',
1213+
enabled: true,
1214+
variationType: VariationType.STRING,
1215+
variations: {
1216+
control: { key: 'control', value: 'control-value' },
1217+
treatment: { key: 'treatment', value: 'treatment-value' },
1218+
},
1219+
allocations: [
1220+
{
1221+
key: 'allocation-1',
1222+
rules: [],
1223+
splits: [
1224+
{
1225+
shards: [],
1226+
variationKey: 'treatment',
1227+
},
1228+
],
1229+
doLog: true,
1230+
},
1231+
],
1232+
totalShards: 10000,
1233+
};
1234+
1235+
// Sample bandit variation with correct shape
1236+
const testBanditVariation: BanditVariation = {
1237+
key: 'test-bandit',
1238+
flagKey: 'test-flag',
1239+
variationKey: 'treatment',
1240+
variationValue: 'treatment-value',
1241+
};
1242+
1243+
// Sample bandit parameters with correct shape
1244+
const testBanditParameters: BanditParameters = {
1245+
banditKey: 'test-bandit',
1246+
modelName: 'test-model',
1247+
modelVersion: '1.0',
1248+
modelData: {
1249+
gamma: 0,
1250+
defaultActionScore: 0,
1251+
actionProbabilityFloor: 0,
1252+
coefficients: {},
1253+
},
1254+
};
1255+
1256+
beforeEach(() => {
1257+
// Reset mocks
1258+
jest.clearAllMocks();
1259+
1260+
// Create fresh stores for each test
1261+
flagStore = new MemoryOnlyConfigurationStore<Flag | ObfuscatedFlag>();
1262+
banditVariationStore = new MemoryOnlyConfigurationStore<BanditVariation[]>();
1263+
banditModelStore = new MemoryOnlyConfigurationStore<BanditParameters>();
1264+
1265+
// Create client with the stores
1266+
client = new EppoClient({
1267+
flagConfigurationStore: flagStore,
1268+
banditVariationConfigurationStore: banditVariationStore,
1269+
banditModelConfigurationStore: banditModelStore,
1270+
});
1271+
});
1272+
1273+
it('should initialize ConfigurationManager in constructor', () => {
1274+
// Access the private configurationManager field
1275+
const configManager = (client as any).configurationManager;
1276+
1277+
expect(configManager).toBeDefined();
1278+
expect(configManager).toBeInstanceOf(ConfigurationManager);
1279+
});
1280+
1281+
it('should use ConfigurationManager for getConfiguration', () => {
1282+
// Create a spy on the ConfigurationManager's getConfiguration method
1283+
const configManager = (client as any).configurationManager;
1284+
const getConfigSpy = jest.spyOn(configManager, 'getConfiguration');
1285+
1286+
// Call the client's getConfiguration method
1287+
const config = (client as any).getConfiguration();
1288+
1289+
// Verify the manager's method was called
1290+
expect(getConfigSpy).toHaveBeenCalled();
1291+
expect(config).toBe(configManager.getConfiguration());
1292+
});
1293+
1294+
it('should update ConfigurationManager when setFlagConfigurationStore is called', async () => {
1295+
// Create a new store
1296+
const newFlagStore = new MemoryOnlyConfigurationStore<Flag | ObfuscatedFlag>();
1297+
1298+
// Pre-populate with a test flag
1299+
await newFlagStore.setEntries({ 'test-flag': testFlag });
1300+
newFlagStore.setFormat(FormatEnum.SERVER);
1301+
1302+
// Create a spy on the ConfigurationManager's setConfigurationStores method
1303+
const configManager = (client as any).configurationManager;
1304+
const setStoresSpy = jest.spyOn(configManager, 'setConfigurationStores');
1305+
1306+
// Call the setter method
1307+
client.setFlagConfigurationStore(newFlagStore);
1308+
1309+
// Verify the manager's method was called with the correct arguments
1310+
expect(setStoresSpy).toHaveBeenCalledWith(
1311+
expect.objectContaining({
1312+
flagConfigurationStore: newFlagStore,
1313+
}),
1314+
);
1315+
1316+
// Verify the configuration was updated by checking if we can access the flag
1317+
const config = configManager.getConfiguration();
1318+
expect(config.getFlag('test-flag')).toEqual(testFlag);
1319+
});
1320+
1321+
it('should update ConfigurationManager when setBanditVariationConfigurationStore is called', async () => {
1322+
// Create a new store
1323+
const newBanditVariationStore = new MemoryOnlyConfigurationStore<BanditVariation[]>();
1324+
1325+
// Pre-populate with test data
1326+
await newBanditVariationStore.setEntries({
1327+
'test-flag': [testBanditVariation],
1328+
});
1329+
newBanditVariationStore.setFormat(FormatEnum.SERVER);
1330+
1331+
// Create a spy on the ConfigurationManager's setConfigurationStores method
1332+
const configManager = (client as any).configurationManager;
1333+
const setStoresSpy = jest.spyOn(configManager, 'setConfigurationStores');
1334+
1335+
// Call the setter method
1336+
client.setBanditVariationConfigurationStore(newBanditVariationStore);
1337+
1338+
// Verify the manager's method was called with the correct arguments
1339+
expect(setStoresSpy).toHaveBeenCalledWith(
1340+
expect.objectContaining({
1341+
banditReferenceConfigurationStore: newBanditVariationStore,
1342+
}),
1343+
);
1344+
1345+
// Verify the configuration was updated
1346+
const config = configManager.getConfiguration();
1347+
expect(config.getBanditVariations()['test-flag']).toEqual([testBanditVariation]);
1348+
});
1349+
1350+
it('should update ConfigurationManager when setBanditModelConfigurationStore is called', async () => {
1351+
// Create a new store
1352+
const newBanditModelStore = new MemoryOnlyConfigurationStore<BanditParameters>();
1353+
1354+
// Pre-populate with test data
1355+
await newBanditModelStore.setEntries({
1356+
'test-bandit': testBanditParameters,
1357+
});
1358+
newBanditModelStore.setFormat(FormatEnum.SERVER);
1359+
1360+
// Create a spy on the ConfigurationManager's setConfigurationStores method
1361+
const configManager = (client as any).configurationManager;
1362+
const setStoresSpy = jest.spyOn(configManager, 'setConfigurationStores');
1363+
1364+
// Call the setter method
1365+
client.setBanditModelConfigurationStore(newBanditModelStore);
1366+
1367+
// Verify the manager's method was called with the correct arguments
1368+
expect(setStoresSpy).toHaveBeenCalledWith(
1369+
expect.objectContaining({
1370+
banditConfigurationStore: newBanditModelStore,
1371+
}),
1372+
);
1373+
1374+
// Verify the configuration was updated
1375+
const config = configManager.getConfiguration();
1376+
expect(config.getBandits()['test-bandit']).toEqual(testBanditParameters);
1377+
});
1378+
1379+
it('should use configuration from ConfigurationManager for assignment decisions', async () => {
1380+
// Create a new flag store with a test flag
1381+
const newFlagStore = new MemoryOnlyConfigurationStore<Flag | ObfuscatedFlag>();
1382+
await newFlagStore.setEntries({ 'test-flag': testFlag });
1383+
newFlagStore.setFormat(FormatEnum.SERVER);
1384+
1385+
// Update the client's flag store
1386+
client.setFlagConfigurationStore(newFlagStore);
1387+
1388+
// Create a spy on the ConfigurationManager's getConfiguration method
1389+
const configManager = (client as any).configurationManager;
1390+
const getConfigSpy = jest.spyOn(configManager, 'getConfiguration');
1391+
1392+
// Get an assignment
1393+
const assignment = client.getStringAssignment('test-flag', 'subject-1', {}, 'default');
1394+
1395+
// Verify the manager's getConfiguration method was called
1396+
expect(getConfigSpy).toHaveBeenCalled();
1397+
1398+
// Verify we got the expected assignment (based on the test flag's configuration)
1399+
expect(assignment).toBe('treatment-value');
1400+
});
1401+
1402+
it('should reflect changes in ConfigurationManager immediately in assignments', async () => {
1403+
// First, set up a flag store with one variation
1404+
const initialFlagStore = new MemoryOnlyConfigurationStore<Flag | ObfuscatedFlag>();
1405+
const initialFlag = { ...testFlag };
1406+
await initialFlagStore.setEntries({ 'test-flag': initialFlag });
1407+
initialFlagStore.setFormat(FormatEnum.SERVER);
1408+
1409+
client.setFlagConfigurationStore(initialFlagStore);
1410+
1411+
// Get initial assignment
1412+
const initialAssignment = client.getStringAssignment('test-flag', 'subject-1', {}, 'default');
1413+
expect(initialAssignment).toBe('treatment-value');
1414+
1415+
// Now create a new flag store with a different variation
1416+
const updatedFlagStore = new MemoryOnlyConfigurationStore<Flag | ObfuscatedFlag>();
1417+
const updatedFlag = {
1418+
...testFlag,
1419+
variations: {
1420+
control: { key: 'control', value: 'control-value' },
1421+
treatment: { key: 'treatment', value: 'new-treatment-value' },
1422+
},
1423+
};
1424+
await updatedFlagStore.setEntries({ 'test-flag': updatedFlag });
1425+
updatedFlagStore.setFormat(FormatEnum.SERVER);
1426+
1427+
// Update the client's flag store
1428+
client.setFlagConfigurationStore(updatedFlagStore);
1429+
1430+
// Get updated assignment
1431+
const updatedAssignment = client.getStringAssignment('test-flag', 'subject-1', {}, 'default');
1432+
1433+
// Verify the assignment reflects the updated configuration
1434+
expect(updatedAssignment).toBe('new-treatment-value');
1435+
});
1436+
});

src/configuration-store/configuration-manager.spec.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,6 @@ describe('ConfigurationManager', () => {
151151
flagKey: 'test-flag',
152152
variationKey: 'bandit-var',
153153
variationValue: 'bandit',
154-
// allocationKey: 'allocation-1',
155154
},
156155
],
157156
},
@@ -250,7 +249,6 @@ describe('ConfigurationManager', () => {
250249
flagKey: 'test-flag',
251250
variationKey: 'bandit-var',
252251
variationValue: 'bandit',
253-
// allocationKey: 'allocation-1',
254252
},
255253
],
256254
},
@@ -290,7 +288,6 @@ describe('ConfigurationManager', () => {
290288
flagKey: 'test-flag',
291289
variationKey: 'bandit-var',
292290
variationValue: 'bandit',
293-
// allocationKey: 'allocation-1',
294291
},
295292
],
296293
},
@@ -397,7 +394,6 @@ describe('ConfigurationManager', () => {
397394
flagKey: 'test-flag',
398395
variationKey: 'var-a',
399396
variationValue: 'A',
400-
// allocationKey: 'allocation-1',
401397
},
402398
],
403399
},
@@ -498,14 +494,12 @@ describe('ConfigurationManager', () => {
498494
flagKey: 'flag-1',
499495
variationKey: 'var-a',
500496
variationValue: 'A',
501-
// allocationKey: 'alloc-1',
502497
},
503498
{
504499
key: 'bandit-1-var-2',
505500
flagKey: 'flag-2',
506501
variationKey: 'var-b',
507502
variationValue: 'B',
508-
// allocationKey: 'alloc-2',
509503
},
510504
],
511505
},
@@ -517,7 +511,6 @@ describe('ConfigurationManager', () => {
517511
flagKey: 'flag-1',
518512
variationKey: 'var-c',
519513
variationValue: 'C',
520-
// allocationKey: 'alloc-3',
521514
},
522515
],
523516
},

0 commit comments

Comments
 (0)