Skip to content

Commit

Permalink
feat(flagd): add flag metadata (#1151)
Browse files Browse the repository at this point in the history
Signed-off-by: Michael Beemer <[email protected]>
  • Loading branch information
beeme1mr authored Jan 10, 2025
1 parent 5b2ac49 commit b1c6d23
Show file tree
Hide file tree
Showing 22 changed files with 152 additions and 369 deletions.
10 changes: 5 additions & 5 deletions libs/providers/flagd-web/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,12 @@
]
},
"e2e": {
"executor": "nx:run-commands",
"executor": "@nx/jest:jest",
"outputs": [
"{workspaceRoot}/coverage/libs/providers/flagd-web"
],
"options": {
"commands": [
"npx jest"
],
"cwd": "libs/providers/flagd-web/src/e2e",
"jestConfig": "libs/providers/flagd-web/src/e2e/jest.config.ts",
"parallel": false
},
"dependsOn": [
Expand Down
2 changes: 1 addition & 1 deletion libs/providers/flagd-web/src/e2e/constants.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { getGherkinTestPath } from '@openfeature/flagd-core';

export const FLAGD_NAME = 'flagd-web';
export const FLAGD_NAME = 'flagd';

export const GHERKIN_EVALUATION_FEATURE = getGherkinTestPath('flagd.feature');
18 changes: 8 additions & 10 deletions libs/providers/flagd-web/src/e2e/jest.config.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
export default {
import type { Config } from 'jest';

const config: Config = {
displayName: 'providers-flagd-web-e2e',
transform: {
'^.+\\.[tj]s$': ['ts-jest', { tsconfig: './tsconfig.lib.json' }],
},
clearMocks: true,
preset: 'ts-jest',
moduleNameMapper: {
'@openfeature/flagd-core': ['<rootDir>/../../../../shared/flagd-core/src'],
'^(.*)\\.js$': ['$1.js', '$1.ts', '$1'],
'(.+)\\.js$': '$1',
},
testEnvironment: 'node',
preset: 'ts-jest',
clearMocks: true,
setupFiles: [],
verbose: true,
silent: false,
};

export default config;
67 changes: 30 additions & 37 deletions libs/providers/flagd-web/src/e2e/step-definitions/flag.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { StepDefinitions } from 'jest-cucumber';
import {
EvaluationContext,
EvaluationDetails,
FlagValue,
JsonObject,
Expand All @@ -13,10 +12,8 @@ import { E2E_CLIENT_NAME } from '@openfeature/flagd-core';
export const flagStepDefinitions: StepDefinitions = ({ given, and, when, then }) => {
let flagKey: string;
let value: FlagValue;
let context: EvaluationContext = {};
let details: EvaluationDetails<FlagValue>;
let fallback: FlagValue;
let flagsChanged: string[];

const client = OpenFeature.getClient(E2E_CLIENT_NAME);

Expand All @@ -26,19 +23,15 @@ export const flagStepDefinitions: StepDefinitions = ({ given, and, when, then })
});
});

beforeEach(() => {
context = {};
});

given('a provider is registered', () => undefined);
given('a flagd provider is set', () => undefined);

when(
/^a boolean flag with key "(.*)" is evaluated with default value "(.*)"$/,
async (key: string, defaultValue: string) => {
(key: string, defaultValue: string) => {
flagKey = key;
fallback = defaultValue;
value = await client.getBooleanValue(key, defaultValue === 'true');
value = client.getBooleanValue(key, defaultValue === 'true');
},
);

Expand All @@ -48,10 +41,10 @@ export const flagStepDefinitions: StepDefinitions = ({ given, and, when, then })

when(
/^a string flag with key "(.*)" is evaluated with default value "(.*)"$/,
async (key: string, defaultValue: string) => {
(key: string, defaultValue: string) => {
flagKey = key;
fallback = defaultValue;
value = await client.getStringValue(key, defaultValue);
value = client.getStringValue(key, defaultValue);
},
);

Expand All @@ -64,7 +57,7 @@ export const flagStepDefinitions: StepDefinitions = ({ given, and, when, then })
async (key: string, defaultValue: string) => {
flagKey = key;
fallback = Number(defaultValue);
value = await client.getNumberValue(key, Number.parseInt(defaultValue));
value = client.getNumberValue(key, Number.parseInt(defaultValue));
},
);

Expand All @@ -77,7 +70,7 @@ export const flagStepDefinitions: StepDefinitions = ({ given, and, when, then })
async (key: string, defaultValue: string) => {
flagKey = key;
fallback = Number(defaultValue);
value = await client.getNumberValue(key, Number.parseFloat(defaultValue));
value = client.getNumberValue(key, Number.parseFloat(defaultValue));
},
);

Expand All @@ -89,7 +82,7 @@ export const flagStepDefinitions: StepDefinitions = ({ given, and, when, then })
const defaultValue = {};
flagKey = key;
fallback = '';
value = await client.getObjectValue(key, defaultValue);
value = client.getObjectValue(key, defaultValue);
});

then(
Expand All @@ -107,7 +100,7 @@ export const flagStepDefinitions: StepDefinitions = ({ given, and, when, then })
async (key: string, defaultValue: string) => {
flagKey = key;
fallback = defaultValue;
details = await client.getBooleanDetails(key, defaultValue === 'true');
details = client.getBooleanDetails(key, defaultValue === 'true');
},
);

Expand All @@ -123,10 +116,10 @@ export const flagStepDefinitions: StepDefinitions = ({ given, and, when, then })

when(
/^a string flag with key "(.*)" is evaluated with details and default value "(.*)"$/,
async (key: string, defaultValue: string) => {
(key: string, defaultValue: string) => {
flagKey = key;
fallback = defaultValue;
details = await client.getStringDetails(key, defaultValue);
details = client.getStringDetails(key, defaultValue);
},
);

Expand All @@ -142,10 +135,10 @@ export const flagStepDefinitions: StepDefinitions = ({ given, and, when, then })

when(
/^an integer flag with key "(.*)" is evaluated with details and default value (\d+)$/,
async (key: string, defaultValue: string) => {
(key: string, defaultValue: string) => {
flagKey = key;
fallback = defaultValue;
details = await client.getNumberDetails(key, Number.parseInt(defaultValue));
details = client.getNumberDetails(key, Number.parseInt(defaultValue));
},
);

Expand All @@ -161,10 +154,10 @@ export const flagStepDefinitions: StepDefinitions = ({ given, and, when, then })

when(
/^a float flag with key "(.*)" is evaluated with details and default value (\d+\.?\d*)$/,
async (key: string, defaultValue: string) => {
(key: string, defaultValue: string) => {
flagKey = key;
fallback = defaultValue;
details = await client.getNumberDetails(key, Number.parseFloat(defaultValue));
details = client.getNumberDetails(key, Number.parseFloat(defaultValue));
},
);

Expand All @@ -178,10 +171,10 @@ export const flagStepDefinitions: StepDefinitions = ({ given, and, when, then })
},
);

when(/^an object flag with key "(.*)" is evaluated with details and a null default value$/, async (key: string) => {
when(/^an object flag with key "(.*)" is evaluated with details and a null default value$/, (key: string) => {
flagKey = key;
fallback = {};
details = await client.getObjectDetails(key, {});
details = client.getObjectDetails(key, {});
});

then(
Expand Down Expand Up @@ -211,10 +204,10 @@ export const flagStepDefinitions: StepDefinitions = ({ given, and, when, then })

when(
/^a non-existent string flag with key "(.*)" is evaluated with details and a default value "(.*)"$/,
async (key: string, defaultValue: string) => {
(key: string, defaultValue: string) => {
flagKey = key;
fallback = defaultValue;
details = await client.getStringDetails(flagKey, defaultValue);
details = client.getStringDetails(flagKey, defaultValue);
},
);

Expand All @@ -234,10 +227,10 @@ export const flagStepDefinitions: StepDefinitions = ({ given, and, when, then })

when(
/^a string flag with key "(.*)" is evaluated as an integer, with details and a default value (\d+)$/,
async (key: string, defaultValue: string) => {
(key: string, defaultValue: string) => {
flagKey = key;
fallback = Number.parseInt(defaultValue);
details = await client.getNumberDetails(flagKey, Number.parseInt(defaultValue));
details = client.getNumberDetails(flagKey, Number.parseInt(defaultValue));
},
);

Expand Down Expand Up @@ -266,7 +259,7 @@ export const flagStepDefinitions: StepDefinitions = ({ given, and, when, then })
});

when('a PROVIDER_CONFIGURATION_CHANGED handler is added', () => {
client.addHandler(ProviderEvents.ConfigurationChanged, async (details) => {
client.addHandler(ProviderEvents.ConfigurationChanged, async () => {
// file writes are not atomic, so we get a few events in quick succession from the testbed
// some will not contain changes, this tolerates that; at least 1 should have our change

Expand All @@ -290,7 +283,7 @@ export const flagStepDefinitions: StepDefinitions = ({ given, and, when, then })
expect(ran).toBeTruthy();
});

and(/^the event details must indicate "(.*)" was altered$/, (flagName) => {
and(/^the event details must indicate "(.*)" was altered$/, () => {
// TODO: enable this for testing of issue
//expect(flagsChanged).toContain(flagName);
});
Expand All @@ -303,9 +296,9 @@ export const flagStepDefinitions: StepDefinitions = ({ given, and, when, then })
},
);

then(/^the resolved boolean zero-value should be "(.*)"$/, async (expectedVal: string) => {
then(/^the resolved boolean zero-value should be "(.*)"$/, (expectedVal: string) => {
const expectedValue = expectedVal === 'true';
const value = await client.getBooleanValue(flagKey, fallback as boolean);
const value = client.getBooleanValue(flagKey, fallback as boolean);
expect(value).toEqual(expectedValue);
});

Expand All @@ -314,8 +307,8 @@ export const flagStepDefinitions: StepDefinitions = ({ given, and, when, then })
fallback = defaultVal;
});

then('the resolved string zero-value should be ""', async () => {
const value = await client.getStringValue(flagKey, fallback as string);
then('the resolved string zero-value should be ""', () => {
const value = client.getStringValue(flagKey, fallback as string);
expect(value).toEqual('');
});

Expand All @@ -324,9 +317,9 @@ export const flagStepDefinitions: StepDefinitions = ({ given, and, when, then })
fallback = defaultVal;
});

then(/^the resolved integer zero-value should be (\d+)$/, async (expectedValueString) => {
then(/^the resolved integer zero-value should be (\d+)$/, (expectedValueString) => {
const expectedValue = Number.parseInt(expectedValueString);
const value = await client.getNumberValue(flagKey, fallback as number);
const value = client.getNumberValue(flagKey, fallback as number);
expect(value).toEqual(expectedValue);
});

Expand All @@ -338,9 +331,9 @@ export const flagStepDefinitions: StepDefinitions = ({ given, and, when, then })
},
);

then(/^the resolved float zero-value should be (\d+\.\d+)$/, async (expectedValueString) => {
then(/^the resolved float zero-value should be (\d+\.\d+)$/, (expectedValueString) => {
const expectedValue = Number.parseFloat(expectedValueString);
const value = await client.getNumberValue(flagKey, fallback as number);
const value = client.getNumberValue(flagKey, fallback as number);
expect(value).toEqual(expectedValue);
});

Expand Down
12 changes: 0 additions & 12 deletions libs/providers/flagd-web/src/e2e/tsconfig.lib.json

This file was deleted.

24 changes: 3 additions & 21 deletions libs/providers/flagd-web/src/lib/flagd-web-provider.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
JsonValue,
OpenFeature,
ProviderEvents,
ProviderStatus,
StandardResolutionReasons,
} from '@openfeature/web-sdk';
import fetchMock from 'jest-fetch-mock';
Expand Down Expand Up @@ -193,21 +192,12 @@ describe(FlagdWebProvider.name, () => {

describe(ProviderEvents.Ready, () => {
it('should fire as soon as client subscribes, if ready', (done) => {
try {
// should start NOT_READY
expect(provider.status).toEqual(ProviderStatus.NOT_READY);
done();
} catch (err) {
done(err);
}

mockCallbackClient.mockMessage({
type: EVENT_PROVIDER_READY,
});

client.addHandler(ProviderEvents.Ready, () => {
try {
expect(provider.status).toEqual(ProviderStatus.READY);
done();
} catch (err) {
done(err);
Expand All @@ -216,22 +206,14 @@ describe(FlagdWebProvider.name, () => {
});

it('should fire and be ready if message received', (done) => {
try {
// should start NOT_READY
expect(provider.status).toEqual(ProviderStatus.NOT_READY);
done();
} catch (err) {
done(err);
}

client.addHandler(ProviderEvents.Ready, () => {
try {
expect(provider.status).toEqual(ProviderStatus.READY);
done();
} catch (err) {
done(err);
}
});

mockCallbackClient.mockMessage({
type: EVENT_PROVIDER_READY,
});
Expand Down Expand Up @@ -269,9 +251,9 @@ describe(FlagdWebProvider.name, () => {

describe(ProviderEvents.Error, () => {
it('should fire if message received', (done) => {
client.addHandler(ProviderEvents.Error, () => {
client.addHandler(ProviderEvents.Error, (event) => {
try {
expect(provider.status).toEqual(ProviderStatus.ERROR);
expect(event?.providerName).toBe('flagd');
done();
} catch (err) {
done(err);
Expand Down
Loading

0 comments on commit b1c6d23

Please sign in to comment.