Skip to content

[FSSDK-11238] Test conversions notification_center and utils #1020

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
12 changes: 9 additions & 3 deletions lib/core/bucketer/bucket_value_generator.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,14 @@ describe('generateBucketValue', () => {
it('should return an error if it cannot generate the hash value', () => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
expect(() => generateBucketValue(null)).toThrowError(
new OptimizelyError(INVALID_BUCKETING_ID)
);
expect(() => generateBucketValue(null)).toThrow(OptimizelyError);
try {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
generateBucketValue(null);
} catch (err) {
expect(err).toBeInstanceOf(OptimizelyError);
expect(err.baseMessage).toBe(INVALID_BUCKETING_ID);
}
});
});
11 changes: 8 additions & 3 deletions lib/core/bucketer/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,9 +198,14 @@ describe('including groups: random', () => {
const bucketerParamsWithInvalidGroupId = cloneDeep(bucketerParams);
bucketerParamsWithInvalidGroupId.experimentIdMap[configObj.experiments[4].id].groupId = '6969';

expect(() => bucketer.bucket(bucketerParamsWithInvalidGroupId)).toThrowError(
new OptimizelyError(INVALID_GROUP_ID, '6969')
);
expect(()=> bucketer.bucket(bucketerParamsWithInvalidGroupId)).toThrow(OptimizelyError);

try {
bucketer.bucket(bucketerParamsWithInvalidGroupId);
} catch(err) {
expect(err).toBeInstanceOf(OptimizelyError);
expect(err.baseMessage).toBe(INVALID_GROUP_ID);
}
});
});

Expand Down
606 changes: 606 additions & 0 deletions lib/notification_center/index.spec.ts

Large diffs are not rendered by default.

3 changes: 0 additions & 3 deletions lib/project_config/project_config.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -322,9 +322,6 @@ describe('getLayerId', () => {
});

it('should throw error for invalid experiment key in getLayerId', function() {
// expect(() => projectConfig.getLayerId(configObj, 'invalidExperimentKey')).toThrowError(
// sprintf(INVALID_EXPERIMENT_ID, 'PROJECT_CONFIG', 'invalidExperimentKey')
// );
expect(() => projectConfig.getLayerId(configObj, 'invalidExperimentKey')).toThrowError(
expect.objectContaining({
baseMessage: INVALID_EXPERIMENT_ID,
Expand Down
115 changes: 115 additions & 0 deletions lib/utils/attributes_validator/index.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/**
* Copyright 2025, Optimizely
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { describe, it, expect } from 'vitest';
import * as attributesValidator from './';
import { INVALID_ATTRIBUTES, UNDEFINED_ATTRIBUTE } from 'error_message';
import { OptimizelyError } from '../../error/optimizly_error';

describe('validate', () => {
it('should validate the given attributes if attributes is an object', () => {
expect(attributesValidator.validate({ testAttribute: 'testValue' })).toBe(true);
});

it('should throw an error if attributes is an array', () => {
const attributesArray = ['notGonnaWork'];

expect(() => attributesValidator.validate(attributesArray)).toThrow(OptimizelyError);

try {
attributesValidator.validate(attributesArray);
} catch (err) {
expect(err).toBeInstanceOf(OptimizelyError);
expect(err.baseMessage).toBe(INVALID_ATTRIBUTES);
}
});

it('should throw an error if attributes is null', () => {
expect(() => attributesValidator.validate(null)).toThrowError(OptimizelyError);

try {
attributesValidator.validate(null);
} catch (err) {
expect(err).toBeInstanceOf(OptimizelyError);
expect(err.baseMessage).toBe(INVALID_ATTRIBUTES);
}
});

it('should throw an error if attributes is a function', () => {
function invalidInput() {
console.log('This is an invalid input!');
}

expect(() => attributesValidator.validate(invalidInput)).toThrowError(OptimizelyError);

try {
attributesValidator.validate(invalidInput);
} catch(err) {
expect(err).toBeInstanceOf(OptimizelyError);
expect(err.baseMessage).toBe(INVALID_ATTRIBUTES);
}
});

it('should throw an error if attributes contains a key with an undefined value', () => {
const attributeKey = 'testAttribute';
const attributes: Record<string, unknown> = {};
attributes[attributeKey] = undefined;

expect(() => attributesValidator.validate(attributes)).toThrowError(OptimizelyError);

try {
attributesValidator.validate(attributes);
} catch(err) {
expect(err).toBeInstanceOf(OptimizelyError);
expect(err.baseMessage).toBe(UNDEFINED_ATTRIBUTE);
expect(err.params).toEqual([attributeKey]);
}
});
});

describe('isAttributeValid', () => {
it('isAttributeValid returns true for valid values', () => {
const userAttributes: Record<string, unknown> = {
browser_type: 'Chrome',
is_firefox: false,
num_users: 10,
pi_value: 3.14,
'': 'javascript',
};

Object.keys(userAttributes).forEach(key => {
const value = userAttributes[key];

expect(attributesValidator.isAttributeValid(key, value)).toBe(true);
});
});
it('isAttributeValid returns false for invalid values', () => {
const userAttributes: Record<string, unknown> = {
null: null,
objects: { a: 'b' },
array: [1, 2, 3],
infinity: Infinity,
negativeInfinity: -Infinity,
NaN: NaN,
};

Object.keys(userAttributes).forEach(key => {
const value = userAttributes[key];

expect(attributesValidator.isAttributeValid(key, value)).toBe(false);
});
});
});
65 changes: 65 additions & 0 deletions lib/utils/config_validator/index.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/**
* Copyright 2025, Optimizely
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { describe, it, expect } from 'vitest';
import configValidator from './';
import testData from '../../tests/test_data';
import { INVALID_DATAFILE_MALFORMED, INVALID_DATAFILE_VERSION, NO_DATAFILE_SPECIFIED } from 'error_message';
import { OptimizelyError } from '../../error/optimizly_error';

describe('validate', () => {
it('should complain if datafile is not provided', () => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
expect(() => configValidator.validateDatafile()).toThrow(OptimizelyError);

try {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
configValidator.validateDatafile();
} catch (err) {
expect(err).toBeInstanceOf(OptimizelyError);
expect(err.baseMessage).toBe(NO_DATAFILE_SPECIFIED);
}
});

it('should complain if datafile is malformed', () => {
expect(() => configValidator.validateDatafile('abc')).toThrow( OptimizelyError);

try {
configValidator.validateDatafile('abc');
} catch(err) {
expect(err).toBeInstanceOf(OptimizelyError);
expect(err.baseMessage).toBe(INVALID_DATAFILE_MALFORMED);
}
});

it('should complain if datafile version is not supported', () => {
expect(() => configValidator.validateDatafile(JSON.stringify(testData.getUnsupportedVersionConfig())).toThrow(OptimizelyError));

try {
configValidator.validateDatafile(JSON.stringify(testData.getUnsupportedVersionConfig()));
} catch(err) {
expect(err).toBeInstanceOf(OptimizelyError);
expect(err.baseMessage).toBe(INVALID_DATAFILE_VERSION);
expect(err.params).toEqual(['5']);
}
});

it('should not complain if datafile is valid', () => {
expect(() => configValidator.validateDatafile(JSON.stringify(testData.getTestProjectConfig())).not.toThrowError());
});
});
88 changes: 88 additions & 0 deletions lib/utils/event_tag_utils/index.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/**
* Copyright 2025, Optimizely
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { describe, it, expect, beforeEach } from 'vitest';
import * as eventTagUtils from './';
import {
FAILED_TO_PARSE_REVENUE,
PARSED_REVENUE_VALUE,
PARSED_NUMERIC_VALUE,
FAILED_TO_PARSE_VALUE,
} from 'log_message';
import { getMockLogger } from '../../tests/mock/mock_logger';
import { LoggerFacade } from '../../logging/logger';

describe('getRevenueValue', () => {
let logger: LoggerFacade;

beforeEach(() => {
logger = getMockLogger();
});

it('should return the parseed integer for a valid revenue value', () => {
let parsedRevenueValue = eventTagUtils.getRevenueValue({ revenue: '1337' }, logger);

expect(parsedRevenueValue).toBe(1337);
expect(logger.info).toHaveBeenCalledWith(PARSED_REVENUE_VALUE, 1337);

parsedRevenueValue = eventTagUtils.getRevenueValue({ revenue: '13.37' }, logger);

expect(parsedRevenueValue).toBe(13);
});

it('should return null and log a message for invalid value', () => {
const parsedRevenueValue = eventTagUtils.getRevenueValue({ revenue: 'invalid' }, logger);

expect(parsedRevenueValue).toBe(null);
expect(logger.info).toHaveBeenCalledWith(FAILED_TO_PARSE_REVENUE, 'invalid');
});

it('should return null if the revenue value is not present in the event tags', () => {
const parsedRevenueValue = eventTagUtils.getRevenueValue({ not_revenue: '1337' }, logger);

expect(parsedRevenueValue).toBe(null);
});
});

describe('getEventValue', () => {
let logger: LoggerFacade;

beforeEach(() => {
logger = getMockLogger();
});

it('should return the parsed integer for a valid numeric value', () => {
let parsedEventValue = eventTagUtils.getEventValue({ value: '1337' }, logger);

expect(parsedEventValue).toBe(1337);
expect(logger.info).toHaveBeenCalledWith(PARSED_NUMERIC_VALUE, 1337);

parsedEventValue = eventTagUtils.getEventValue({ value: '13.37' }, logger);
expect(parsedEventValue).toBe(13.37);
});

it('should return null and log a message for invalid value', () => {
const parsedNumericValue = eventTagUtils.getEventValue({ value: 'invalid' }, logger);

expect(parsedNumericValue).toBe(null);
expect(logger.info).toHaveBeenCalledWith(FAILED_TO_PARSE_VALUE, 'invalid');
});

it('should return null if the value is not present in the event tags', () => {
const parsedNumericValue = eventTagUtils.getEventValue({ not_value: '13.37' }, logger);

expect(parsedNumericValue).toBe(null);
});
})
63 changes: 63 additions & 0 deletions lib/utils/event_tags_validator/index.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/**
* Copyright 2025, Optimizely
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { describe, it, expect, beforeEach } from 'vitest';
import { validate } from '.';
import { OptimizelyError } from '../../error/optimizly_error';
import { INVALID_EVENT_TAGS } from 'error_message';

describe('validate', () => {
it('should validate the given event tags if event tag is an object', () => {
expect(validate({ testAttribute: 'testValue' })).toBe(true);
});

it('should throw an error if event tags is an array', () => {
const eventTagsArray = ['notGonnaWork'];

expect(() => validate(eventTagsArray)).toThrow(OptimizelyError)

try {
validate(eventTagsArray);
} catch(err) {
expect(err).toBeInstanceOf(OptimizelyError);
expect(err.baseMessage).toBe(INVALID_EVENT_TAGS);
}
});

it('should throw an error if event tags is null', () => {
expect(() => validate(null)).toThrow(OptimizelyError);

try {
validate(null);
} catch(err) {
expect(err).toBeInstanceOf(OptimizelyError);
expect(err.baseMessage).toBe(INVALID_EVENT_TAGS);
}
});

it('should throw an error if event tags is a function', () => {
function invalidInput() {
console.log('This is an invalid input!');
}
expect(() => validate(invalidInput)).toThrow(OptimizelyError);

try {
validate(invalidInput);
} catch(err) {
expect(err).toBeInstanceOf(OptimizelyError);
expect(err.baseMessage).toBe(INVALID_EVENT_TAGS);
}
});
});
Loading
Loading