464 lines
15 KiB
TypeScript

import {
isSchema,
isFileSchema,
inSameDomain,
getFileCssName,
isJSSlot,
getValue,
getI18n,
transformArrayToMap,
transformStringToFunction,
isVariable,
capitalizeFirstLetter,
forEach,
isString,
serializeParams,
parseExpression,
parseThisRequiredExpression,
parseI18n,
parseData,
} from '../../src/utils/common';
import logger from '../../src/utils/logger';
describe('test isSchema', () => {
it('should be false when empty value is passed', () => {
expect(isSchema(null)).toBeFalsy();
expect(isSchema(undefined)).toBeFalsy();
expect(isSchema('')).toBeFalsy();
expect(isSchema({})).toBeFalsy();
});
it('should be true when componentName is Leaf or Slot ', () => {
expect(isSchema({ componentName: 'Leaf' })).toBeTruthy();
expect(isSchema({ componentName: 'Slot' })).toBeTruthy();
});
it('should check each item of an array', () => {
const validArraySchema = [
{ componentName: 'Button', props: {}},
{ componentName: 'Button', props: { type: 'JSExpression' }},
{ componentName: 'Leaf' },
{ componentName: 'Slot'},
];
const invalidArraySchema = [
...validArraySchema,
{ componentName: 'ComponentWithoutProps'},
];
expect(isSchema(validArraySchema)).toBeTruthy();
expect(isSchema(invalidArraySchema)).toBeFalsy();
});
it('normal valid schema should contains componentName, and props of type object or JSExpression', () => {
expect(isSchema({ componentName: 'Button', props: {}})).toBeTruthy();
expect(isSchema({ componentName: 'Button', props: { type: 'JSExpression' }})).toBeTruthy();
expect(isSchema({ xxxName: 'Button'})).toBeFalsy();
expect(isSchema({ componentName: 'Button', props: null})).toBeFalsy();
expect(isSchema({ componentName: 'Button', props: []})).toBeFalsy();
expect(isSchema({ componentName: 'Button', props: 'props string'})).toBeFalsy();
});
});
describe('test isFileSchema ', () => {
it('should be false when invalid schema is passed', () => {
expect(isFileSchema({ xxxName: 'Button'})).toBeFalsy();
expect(isFileSchema({ componentName: 'Button', props: null})).toBeFalsy();
expect(isFileSchema({ componentName: 'Button', props: []})).toBeFalsy();
expect(isFileSchema({ componentName: 'Button', props: 'props string'})).toBeFalsy();
});
it('should be true only when schema with root named Page || Block || Component is passed', () => {
expect(isFileSchema({ componentName: 'Page', props: {}})).toBeTruthy();
expect(isFileSchema({ componentName: 'Block', props: {}})).toBeTruthy();
expect(isFileSchema({ componentName: 'Component', props: {}})).toBeTruthy();
expect(isFileSchema({ componentName: 'Button', props: {}})).toBeFalsy();
});
});
describe('test inSameDomain ', () => {
let windowSpy;
beforeEach(() => {
windowSpy = jest.spyOn(window, "window", "get");
});
afterEach(() => {
windowSpy.mockRestore();
});
it('should work', () => {
windowSpy.mockImplementation(() => ({
parent: {
location: {
host: "example.com"
},
},
location: {
host: "example.com"
}
}));
expect(inSameDomain()).toBeTruthy();
windowSpy.mockImplementation(() => ({
parent: {
location: {
host: "example.com"
},
},
location: {
host: "another.com"
}
}));
expect(inSameDomain()).toBeFalsy();
windowSpy.mockImplementation(() => ({
parent: null,
location: {
host: "example.com"
}
}));
expect(inSameDomain()).toBeFalsy();
});
});
describe('test getFileCssName ', () => {
it('should work', () => {
expect(getFileCssName(null)).toBe(undefined);
expect(getFileCssName(undefined)).toBe(undefined);
expect(getFileCssName('')).toBe(undefined);
expect(getFileCssName('FileName')).toBe('lce-file-name');
expect(getFileCssName('Page1_abc')).toBe('lce-page1_abc');
});
});
describe('test isJSSlot ', () => {
it('should work', () => {
expect(isJSSlot(null)).toBeFalsy();
expect(isJSSlot(undefined)).toBeFalsy();
expect(isJSSlot('stringValue')).toBeFalsy();
expect(isJSSlot([1, 2, 3])).toBeFalsy();
expect(isJSSlot({ type: 'JSSlot' })).toBeTruthy();
expect(isJSSlot({ type: 'JSBlock' })).toBeTruthy();
expect(isJSSlot({ type: 'anyOtherType' })).toBeFalsy();
});
});
describe('test getValue ', () => {
it('should check params', () => {
expect(getValue(null, 'somePath')).toStrictEqual({});
expect(getValue(undefined, 'somePath')).toStrictEqual({});
// array is not valid input, return default
expect(getValue([], 'somePath')).toStrictEqual({});
expect(getValue([], 'somePath', 'aaa')).toStrictEqual('aaa');
expect(getValue([1, 2, 3], 'somePath', 'aaa')).toStrictEqual('aaa');
expect(getValue({}, 'somePath')).toStrictEqual({});
expect(getValue({}, 'somePath', 'default')).toStrictEqual('default');
});
it('should work normally', () => {
// single segment path
expect(getValue({ a: 'aValue' }, 'a')).toStrictEqual('aValue');
expect(getValue({ a: 'aValue', f:null }, 'f')).toBeNull();
expect(getValue({ a: { b: 'bValue' } }, 'a.b')).toStrictEqual('bValue');
expect(getValue({ a: { b: 'bValue', c: { d: 'dValue' } } }, 'a.c.d')).toStrictEqual('dValue');
expect(getValue({ a: { b: 'bValue', c: { d: 'dValue' } } }, 'e')).toStrictEqual({});
});
});
describe('test getI18n ', () => {
it('should work', () => {
const messages = {
'zh-CN': {
'key1': '啊啊啊',
'key2': '哈哈哈',
},
};
expect(getI18n('keyString', {}, 'zh-CN')).toStrictEqual('');
expect(getI18n('keyString', {}, 'zh-CN', null)).toStrictEqual('');
expect(getI18n('keyString', {}, 'en-US', messages)).toStrictEqual('');
expect(getI18n('key3', {}, 'zh-CN', messages)).toStrictEqual('');
});
});
describe('test transformArrayToMap ', () => {
it('should work', () => {
expect(transformArrayToMap([])).toStrictEqual({});
expect(transformArrayToMap('not a array')).toStrictEqual({});
expect(transformArrayToMap({'not Array': 1})).toStrictEqual({});
let mockArray = [
{
name: 'jack',
age: 2,
},
{
name: 'jack',
age: 20,
}
];
// test override
expect(transformArrayToMap(mockArray, 'name', true).jack.age).toBe(20);
expect(transformArrayToMap(mockArray, 'name').jack.age).toBe(20);
expect(transformArrayToMap(mockArray, 'name', false).jack.age).toBe(2);
mockArray = [
{
name: 'jack',
age: 2,
},
{
name: 'rose',
age: 20,
}
];
// normal case
expect(transformArrayToMap(mockArray, 'name').jack.age).toBe(2);
expect(transformArrayToMap(mockArray, 'name').jack.name).toBe('jack');
expect(transformArrayToMap(mockArray, 'name').rose.age).toBe(20);
// key not exists
expect(transformArrayToMap(mockArray, 'nameEn')).toStrictEqual({});
});
});
describe('test transformStringToFunction ', () => {
it('should work', () => {
const mockFun = jest.fn();
expect(transformStringToFunction(mockFun)).toBe(mockFun);
expect(transformStringToFunction(111)).toBe(111);
let mockFnStr = 'function(){return 111;}';
let fn = transformStringToFunction(mockFnStr);
expect(fn()).toBe(111);
mockFnStr = '() => { return 222; }';
fn = transformStringToFunction(mockFnStr);
expect(fn()).toBe(222);
mockFnStr = 'function getValue() { return 333; }';
fn = transformStringToFunction(mockFnStr);
expect(fn()).toBe(333);
mockFnStr = 'function getValue(aaa) {\
return aaa; \
}';
fn = transformStringToFunction(mockFnStr);
expect(fn(123)).toBe(123);
});
});
describe('test isVariable ', () => {
it('should work', () => {
expect(isVariable(null)).toBeFalsy();
expect(isVariable(undefined)).toBeFalsy();
expect(isVariable([1, 2, 3])).toBeFalsy();
expect(isVariable({})).toBeFalsy();
expect(isVariable({ type: 'any other type' })).toBeFalsy();
expect(isVariable({ type: 'variable' })).toBeTruthy();
});
});
describe('test capitalizeFirstLetter ', () => {
it('should work', () => {
expect(capitalizeFirstLetter(null)).toBeNull();
expect(capitalizeFirstLetter()).toBeUndefined();
expect(capitalizeFirstLetter([1, 2, 3])).toStrictEqual([1, 2, 3]);
expect(capitalizeFirstLetter({ a: 1 })).toStrictEqual({ a: 1 });
expect(capitalizeFirstLetter('')).toStrictEqual('');
expect(capitalizeFirstLetter('a')).toStrictEqual('A');
expect(capitalizeFirstLetter('abcd')).toStrictEqual('Abcd');
});
});
describe('test forEach ', () => {
it('should work', () => {
const mockFn = jest.fn();
forEach(null, mockFn);
expect(mockFn).toBeCalledTimes(0);
forEach(undefined, mockFn);
expect(mockFn).toBeCalledTimes(0);
forEach([1, 2, 3], mockFn);
expect(mockFn).toBeCalledTimes(0);
forEach('stringValue', mockFn);
expect(mockFn).toBeCalledTimes(0);
forEach({ a: 1, b: 2, c: 3 }, mockFn);
expect(mockFn).toBeCalledTimes(3);
const mockFn2 = jest.fn();
forEach({ a: 1 }, mockFn2, { b: 'bbb' });
expect(mockFn2).toHaveBeenCalledWith(1, 'a');
let sum = 0;
const mockFn3 = function(value, key) { sum = value + this.b; };
forEach({ a: 1 }, mockFn3, { b: 10 });
expect(sum).toEqual(11);
});
});
describe('test isString ', () => {
it('should work', () => {
expect(isString(123)).toBeFalsy();
expect(isString([])).toBeFalsy();
expect(isString({})).toBeFalsy();
expect(isString(null)).toBeFalsy();
expect(isString(undefined)).toBeFalsy();
expect(isString(true)).toBeFalsy();
expect(isString('111')).toBeTruthy();
expect(isString(new String('111'))).toBeTruthy();
});
});
describe('test serializeParams ', () => {
it('should work', () => {
const mockParams = { a: 1, b: 2, c: 'cvalue', d:[1, 'a', {}], e: {e1: 'value1', e2: 'value2'}};
const result = serializeParams(mockParams);
const decodedParams = decodeURIComponent(result);
expect(result).toBe('a=1&b=2&c=cvalue&d=%5B1%2C%22a%22%2C%7B%7D%5D&e=%7B%22e1%22%3A%22value1%22%2C%22e2%22%3A%22value2%22%7D');
expect(decodedParams).toBe('a=1&b=2&c=cvalue&d=[1,"a",{}]&e={"e1":"value1","e2":"value2"}');
});
});
describe('test parseExpression ', () => {
it('can handle JSExpression', () => {
const mockExpression = {
"type": "JSExpression",
"value": "function (params) { return this.scopeValue + params.param1 + 5;}"
};
const result = parseExpression(mockExpression, { scopeValue: 1 });
expect(result({ param1: 2 })).toBe((1 + 2 + 5));
});
it('[success] JSExpression handle without this use scopeValue', () => {
const mockExpression = {
"type": "JSExpression",
"value": "state"
};
const result = parseExpression(mockExpression, { state: 1 });
expect(result).toBe((1));
});
it('[success] JSExpression handle without this use scopeValue', () => {
const mockExpression = {
"type": "JSExpression",
"value": "this.state"
};
const result = parseExpression(mockExpression, { state: 1 });
expect(result).toBe((1));
});
});
describe('test parseThisRequiredExpression', () => {
it('can handle JSExpression', () => {
const mockExpression = {
"type": "JSExpression",
"value": "function (params) { return this.scopeValue + params.param1 + 5;}"
};
const result = parseThisRequiredExpression(mockExpression, { scopeValue: 1 });
expect(result({ param1: 2 })).toBe((1 + 2 + 5));
});
it('[error] JSExpression handle without this use scopeValue', () => {
const mockExpression = {
"type": "JSExpression",
"value": "state.text"
};
const fn = logger.error = jest.fn();
parseThisRequiredExpression(mockExpression, { state: { text: 'text' } });
expect(fn).toBeCalledWith(' parseExpression.error', new ReferenceError('state is not defined'), {"type": "JSExpression", "value": "state.text"}, {"state": {"text": "text"}});
});
it('[success] JSExpression handle without this use scopeValue', () => {
const mockExpression = {
"type": "JSExpression",
"value": "this.state"
};
const result = parseThisRequiredExpression(mockExpression, { state: 1 });
expect(result).toBe((1));
});
})
describe('test parseI18n ', () => {
it('can handle normal parseI18n', () => {
const mockI18n = {
"type": "i18n",
"key": "keyA"
};
const mockI18nFun = (key) => { return 'hahaha' + key;};
const result = parseI18n(mockI18n, { i18n: mockI18nFun });
expect(result).toBe('hahahakeyA');
});
});
describe('test parseData ', () => {
it('should work when isJSExpression === true', () => {
const mockExpression = {
"type": "JSExpression",
"value": "function (params) { return this.scopeValue + params.param1 + 5;}"
};
const result = parseData(mockExpression, { scopeValue: 1 });
expect(result({ param1: 2 })).toBe((1 + 2 + 5));
});
it('should work when isI18nData === true', () => {
const mockI18n = {
"type": "i18n",
"key": "keyA"
};
const mockI18nFun = (key) => { return 'hahaha' + key;};
const result = parseData(mockI18n, { i18n: mockI18nFun });
expect(result).toBe('hahahakeyA');
});
it('should work when schema is string', () => {
expect(parseData(' this is a normal string, will be trimmed only ')).toStrictEqual('this is a normal string, will be trimmed only');
});
it('should work when schema is array', () => {
const mockData = [
{
"type": "i18n",
"key": "keyA"
},
' this is a normal string, will be trimmed only ',
];
const mockI18nFun = (key) => { return 'hahaha' + key;};
const result = parseData(mockData, { i18n: mockI18nFun });
expect(result[0]).toStrictEqual('hahahakeyA');
expect(result[1]).toStrictEqual('this is a normal string, will be trimmed only');
});
it('should work when schema is function', () => {
const mockFn = function() { return this.a; };
const result = parseData(mockFn, { a: 111 });
expect(result()).toBe(111);
});
it('should work when schema is null or undefined', () => {
expect(parseData(null)).toBe(null);
expect(parseData(undefined)).toBe(undefined);
});
it('should work when schema is normal object', () => {
expect(parseData({})).toStrictEqual({});
const mockI18nFun = (key) => { return 'hahaha' + key;};
const result = parseData({
key1: {
"type": "i18n",
"key": "keyA"
},
key2: ' this is a normal string, will be trimmed only ',
__privateKey: 'any value',
}, { i18n: mockI18nFun });
expect(result.key1).toStrictEqual('hahahakeyA');
expect(result.key2).toStrictEqual('this is a normal string, will be trimmed only');
expect(result.__privateKey).toBeUndefined();
});
});