@ -0,0 +1,14 @@
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
|
||||
type FeatureFlagMetadata = {
|
||||
label: string;
|
||||
description: string;
|
||||
imagePath: string;
|
||||
};
|
||||
|
||||
export type PublicFeatureFlag = {
|
||||
key: Extract<FeatureFlagKey, never>;
|
||||
metadata: FeatureFlagMetadata;
|
||||
};
|
||||
|
||||
export const PUBLIC_FEATURE_FLAGS: PublicFeatureFlag[] = [];
|
||||
@ -0,0 +1,14 @@
|
||||
import { CustomException } from 'src/utils/custom-exception';
|
||||
|
||||
export class FeatureFlagException extends CustomException {
|
||||
code: FeatureFlagExceptionCode;
|
||||
constructor(message: string, code: FeatureFlagExceptionCode) {
|
||||
super(message, code);
|
||||
}
|
||||
}
|
||||
|
||||
export enum FeatureFlagExceptionCode {
|
||||
INVALID_FEATURE_FLAG_KEY = 'INVALID_FEATURE_FLAG_KEY',
|
||||
FEATURE_FLAG_IS_NOT_PUBLIC = 'FEATURE_FLAG_IS_NOT_PUBLIC',
|
||||
FEATURE_FLAG_NOT_FOUND = 'FEATURE_FLAG_NOT_FOUND',
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
import { CustomException } from 'src/utils/custom-exception';
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
import { CustomException } from 'src/utils/custom-exception';
|
||||
import { isDefined } from 'src/utils/is-defined';
|
||||
|
||||
const assertIsFeatureFlagKey = (
|
||||
|
||||
@ -0,0 +1,109 @@
|
||||
import {
|
||||
AuthException,
|
||||
AuthExceptionCode,
|
||||
} from 'src/engine/core-modules/auth/auth.exception';
|
||||
import { PublicFeatureFlag } from 'src/engine/core-modules/feature-flag/constants/public-feature-flag.const';
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
import { publicFeatureFlagValidator } from 'src/engine/core-modules/feature-flag/validates/is-public-feature-flag.validate';
|
||||
|
||||
jest.mock(
|
||||
'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum',
|
||||
() => ({
|
||||
FeatureFlagKey: {
|
||||
mockKey1: 'MOCK_KEY_1',
|
||||
mockKey2: 'MOCK_KEY_2',
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
const mockPublicFeatureFlag = {
|
||||
key: 'MOCK_KEY_1',
|
||||
metadata: {
|
||||
label: 'Mock Label 1',
|
||||
description: 'Mock Description 1',
|
||||
imagePath: 'mock/path/1',
|
||||
},
|
||||
};
|
||||
|
||||
jest.mock(
|
||||
'src/engine/core-modules/lab/utils/is-public-feature-flag.util',
|
||||
() => ({
|
||||
isPublicFeatureFlag: (
|
||||
key: FeatureFlagKey,
|
||||
): key is PublicFeatureFlag['key'] => {
|
||||
if (!key) return false;
|
||||
|
||||
return key === mockPublicFeatureFlag.key;
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
// Note: We're using a single public flag for testing as it's sufficient to verify
|
||||
// the validator's behavior. The validator's role is to check if a flag exists in
|
||||
// the PUBLIC_FEATURE_FLAGS array, so testing with one flag adequately covers this
|
||||
// functionality. Adding more flags wouldn't increase the test coverage meaningfully.
|
||||
|
||||
describe('publicFeatureFlagValidator', () => {
|
||||
describe('assertIsPublicFeatureFlag', () => {
|
||||
const mockException = new AuthException(
|
||||
'Not a public feature flag',
|
||||
AuthExceptionCode.INVALID_INPUT,
|
||||
);
|
||||
|
||||
it('should not throw for public feature flags', () => {
|
||||
const publicFlag = mockPublicFeatureFlag.key as FeatureFlagKey;
|
||||
|
||||
expect(() => {
|
||||
publicFeatureFlagValidator.assertIsPublicFeatureFlag(
|
||||
publicFlag,
|
||||
mockException,
|
||||
);
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it('should throw the provided exception for non-public feature flags', () => {
|
||||
const nonPublicFlag = 'MOCK_KEY_2' as FeatureFlagKey;
|
||||
|
||||
expect(() => {
|
||||
publicFeatureFlagValidator.assertIsPublicFeatureFlag(
|
||||
nonPublicFlag,
|
||||
mockException,
|
||||
);
|
||||
}).toThrow(mockException);
|
||||
});
|
||||
|
||||
it('should throw the provided exception for undefined key', () => {
|
||||
expect(() => {
|
||||
publicFeatureFlagValidator.assertIsPublicFeatureFlag(
|
||||
undefined as unknown as FeatureFlagKey,
|
||||
mockException,
|
||||
);
|
||||
}).toThrow(mockException);
|
||||
});
|
||||
|
||||
it('should throw the provided exception for null key', () => {
|
||||
expect(() => {
|
||||
publicFeatureFlagValidator.assertIsPublicFeatureFlag(
|
||||
null as unknown as FeatureFlagKey,
|
||||
mockException,
|
||||
);
|
||||
}).toThrow(mockException);
|
||||
});
|
||||
|
||||
it('should maintain type assertion after validation', () => {
|
||||
const publicFlag = mockPublicFeatureFlag;
|
||||
|
||||
const testTypeAssertion = (flag: FeatureFlagKey) => {
|
||||
publicFeatureFlagValidator.assertIsPublicFeatureFlag(
|
||||
flag,
|
||||
mockException,
|
||||
);
|
||||
const _test: PublicFeatureFlag['key'] = flag;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
expect(testTypeAssertion(publicFlag.key as FeatureFlagKey)).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,19 @@
|
||||
import { PublicFeatureFlag } from 'src/engine/core-modules/feature-flag/constants/public-feature-flag.const';
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
import { isPublicFeatureFlag } from 'src/engine/core-modules/lab/utils/is-public-feature-flag.util';
|
||||
import { CustomException } from 'src/utils/custom-exception';
|
||||
|
||||
const assertIsPublicFeatureFlag = (
|
||||
key: FeatureFlagKey,
|
||||
exceptionToThrow: CustomException,
|
||||
): asserts key is PublicFeatureFlag['key'] => {
|
||||
if (!isPublicFeatureFlag(key)) {
|
||||
throw exceptionToThrow;
|
||||
}
|
||||
};
|
||||
|
||||
export const publicFeatureFlagValidator: {
|
||||
assertIsPublicFeatureFlag: typeof assertIsPublicFeatureFlag;
|
||||
} = {
|
||||
assertIsPublicFeatureFlag: assertIsPublicFeatureFlag,
|
||||
};
|
||||
Reference in New Issue
Block a user