Skip to content

Commit

Permalink
Add basic unit tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
kinyoklion committed Aug 28, 2023
1 parent b4709f9 commit 71c4325
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 51 deletions.
2 changes: 1 addition & 1 deletion contract-tests/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ app.get('/', (req, res) => {
'big-segments',
'user-type',
'migrations',
'event-sampling'
'event-sampling',
],
});
});
Expand Down
4 changes: 2 additions & 2 deletions contract-tests/sdkClientEntity.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export function makeSdkConfig(options, tag) {
}

function getExecution(order) {
switch(order) {
switch (order) {
case 'serial': {
return new LDSerialExecution(LDExecutionOrdering.Fixed);
}
Expand Down Expand Up @@ -164,7 +164,7 @@ export async function newSdkClientEntity(options) {
case 'migrationOperation':
const migrationOperation = params.migrationOperation;
const readExecutionOrder = migrationOperation.readExecutionOrder;

const migration = new Migration(client, {
execution: getExecution(readExecutionOrder),
latencyTracking: migrationOperation.trackLatency,
Expand Down
139 changes: 102 additions & 37 deletions packages/shared/sdk-server/__tests__/MigrationOpEvent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,44 @@ describe('given an LDClient with test data', () => {
});
});

it.each([
[LDMigrationStage.Off, { old: true }],
[LDMigrationStage.DualWrite, { old: true }],
[LDMigrationStage.Shadow, { old: true, new: true }],
[LDMigrationStage.RampDown, { new: true }],
[LDMigrationStage.Complete, { new: true }],
])('tracks the invoked methods for reads', async (stage, values) => {
const flagKey = 'migration';
td.update(td.flag(flagKey).valueForAll(stage));

await migration.read(flagKey, { key: 'test' }, stage);
// Feature event.
await events.take();
// Migration event.
const migrationEvent = (await events.take()) as internal.InputMigrationEvent;
expect(migrationEvent.measurements[0].key).toEqual('invoked');
expect(migrationEvent.measurements[0].values).toEqual(values);
});

it.each([
[LDMigrationStage.Off, { old: true }],
[LDMigrationStage.DualWrite, { old: true, new: true }],
[LDMigrationStage.Shadow, { old: true, new: true }],
[LDMigrationStage.RampDown, { old: true, new: true }],
[LDMigrationStage.Complete, { new: true }],
])('tracks the invoked methods for writes', async (stage, values) => {
const flagKey = 'migration';
td.update(td.flag(flagKey).valueForAll(stage));

await migration.write(flagKey, { key: 'test' }, stage);
// Feature event.
await events.take();
// Migration event.
const migrationEvent = (await events.take()) as internal.InputMigrationEvent;
expect(migrationEvent.measurements[0].key).toEqual('invoked');
expect(migrationEvent.measurements[0].values).toEqual(values);
});

it.each([LDMigrationStage.Shadow, LDMigrationStage.Live])(
'can report read latency for new and old',
async (stage) => {
Expand Down Expand Up @@ -338,14 +376,13 @@ describe('given an LDClient with test data', () => {
// Migration event.
const migrationEvent = (await events.take()) as internal.InputMigrationEvent;
// Only check the measurements component of the event.
expect(migrationEvent.measurements).toContainEqual(
{
key: 'error',
values: {
old: true,
},
});
}
expect(migrationEvent.measurements).toContainEqual({
key: 'error',
values: {
old: true,
},
});
},
);

it.each([LDMigrationStage.RampDown, LDMigrationStage.Complete])(
Expand All @@ -359,13 +396,12 @@ describe('given an LDClient with test data', () => {
await events.take();
// Migration event.
const migrationEvent = (await events.take()) as internal.InputMigrationEvent;
expect(migrationEvent.measurements).toContainEqual(
{
key: 'error',
values: {
new: true,
},
});
expect(migrationEvent.measurements).toContainEqual({
key: 'error',
values: {
new: true,
},
});
},
);

Expand All @@ -381,14 +417,13 @@ describe('given an LDClient with test data', () => {
// Migration event.
const migrationEvent = (await events.take()) as internal.InputMigrationEvent;
// Only check the measurements component of the event.
expect(migrationEvent.measurements).toContainEqual(
{
key: 'error',
values: {
old: true,
new: true,
},
});
expect(migrationEvent.measurements).toContainEqual({
key: 'error',
values: {
old: true,
new: true,
},
});
},
);

Expand All @@ -403,13 +438,44 @@ describe('given an LDClient with test data', () => {
await events.take();
// Migration event.
const migrationEvent = (await events.take()) as internal.InputMigrationEvent;
expect(migrationEvent.measurements).toContainEqual(
{
key: 'error',
values: {
old: true,
},
});
expect(migrationEvent.measurements).toContainEqual({
key: 'error',
values: {
old: true,
},
});
},
);

it.each([LDMigrationStage.Off, LDMigrationStage.DualWrite, LDMigrationStage.Shadow])(
'it does not invoke non-authoritative write after an error with authoritative old',
async (stage) => {
const flagKey = 'migration';
td.update(td.flag(flagKey).valueForAll(stage));

await migration.write(flagKey, { key: 'test' }, stage);
// Feature event.
await events.take();
// Migration event.
const migrationEvent = (await events.take()) as internal.InputMigrationEvent;
expect(migrationEvent.measurements[0].key).toEqual('invoked');
expect(migrationEvent.measurements[0].values).toEqual({ old: true });
},
);

it.each([LDMigrationStage.Live, LDMigrationStage.RampDown, LDMigrationStage.Complete])(
'it does not invoke non-authoritative write after an error with authoritative new',
async (stage) => {
const flagKey = 'migration';
td.update(td.flag(flagKey).valueForAll(stage));

await migration.write(flagKey, { key: 'test' }, stage);
// Feature event.
await events.take();
// Migration event.
const migrationEvent = (await events.take()) as internal.InputMigrationEvent;
expect(migrationEvent.measurements[0].key).toEqual('invoked');
expect(migrationEvent.measurements[0].values).toEqual({ new: true });
},
);

Expand All @@ -425,13 +491,12 @@ describe('given an LDClient with test data', () => {
// Migration event.
const migrationEvent = (await events.take()) as internal.InputMigrationEvent;
// Only check the measurements component of the event.
expect(migrationEvent.measurements).toContainEqual(
{
key: 'error',
values: {
new: true,
},
});
expect(migrationEvent.measurements).toContainEqual({
key: 'error',
values: {
new: true,
},
});
},
);
});
Expand Down
18 changes: 10 additions & 8 deletions packages/shared/sdk-server/__tests__/MigrationOpTracker.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { LDConsistencyCheck, LDMigrationStage } from '../src';
import MigrationOpTracker from '../src/MigrationOpTracker';
import { LDMigrationOrigin } from '../src/api/LDMigration';
import MigrationOpTracker from '../src/MigrationOpTracker';

it('does not generate an event if an op is not set', () => {
const tracker = new MigrationOpTracker(
Expand Down Expand Up @@ -45,12 +45,14 @@ it('generates an event if the minimal requirements are met.', () => {
contextKeys: { user: 'bob' },
evaluation: { default: 'off', key: 'flag', reason: { kind: 'FALLTHROUGH' }, value: 'off' },
kind: 'migration_op',
measurements: [{
key: 'invoked',
values: {
old: true,
}
}],
measurements: [
{
key: 'invoked',
values: {
old: true,
},
},
],
operation: 'write',
});
});
Expand Down Expand Up @@ -220,4 +222,4 @@ it('includes when both origins were invoked', () => {
key: 'invoked',
values: { old: true, new: true },
});
});
});
6 changes: 4 additions & 2 deletions packages/shared/sdk-server/src/MigrationOpEventConversion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ function isErrorMeasurement(value: LDMigrationMeasurement): value is LDMigration
return (value as any).kind === undefined && value.key === 'error';
}

function isInvokedMeasurement(value: LDMigrationMeasurement): value is LDMigrationInvokedMeasurement {
function isInvokedMeasurement(
value: LDMigrationMeasurement,
): value is LDMigrationInvokedMeasurement {
return (value as any).kind === undefined && value.key === 'invoked';
}

Expand Down Expand Up @@ -119,7 +121,7 @@ function validateMeasurement(
};
}

if(isInvokedMeasurement(measurement)) {
if (isInvokedMeasurement(measurement)) {
if (!TypeValidators.Object.is(measurement.values)) {
return undefined;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export interface LDMigrationInvokedMeasurement {
values: {
old?: boolean;
new?: boolean;
}
};
}

/**
Expand Down

0 comments on commit 71c4325

Please sign in to comment.