mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2025-12-10 18:03:01 +00:00
test(utils): add ut to package/utils
This commit is contained in:
parent
938c71fb46
commit
621245393f
@ -11,6 +11,7 @@ const jestConfig = {
|
||||
'!**/node_modules/**',
|
||||
'!**/vendor/**',
|
||||
],
|
||||
setupFilesAfterEnv: ['./jest.setup.js'],
|
||||
};
|
||||
|
||||
// 只对本仓库内的 pkg 做 mapping
|
||||
|
||||
1
packages/utils/jest.setup.js
Normal file
1
packages/utils/jest.setup.js
Normal file
@ -0,0 +1 @@
|
||||
import '@testing-library/jest-dom';
|
||||
@ -9,7 +9,7 @@
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
"scripts": {
|
||||
"test": "build-scripts test --config build.test.json",
|
||||
"test": "build-scripts test --config build.test.json --jest-coverage",
|
||||
"build": "build-scripts build"
|
||||
},
|
||||
"dependencies": {
|
||||
@ -21,8 +21,11 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@alib/build-scripts": "^0.1.18",
|
||||
"@testing-library/jest-dom": "^6.1.4",
|
||||
"@testing-library/react": "^11.2.7",
|
||||
"@types/node": "^13.7.1",
|
||||
"@types/react": "^16"
|
||||
"@types/react": "^16",
|
||||
"react-dom": "^16.14.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { IPublicTypeActionContentObject } from '@alilc/lowcode-types';
|
||||
import { isObject } from '../is-object';
|
||||
|
||||
export function isActionContentObject(obj: any): obj is IPublicTypeActionContentObject {
|
||||
return obj && typeof obj === 'object';
|
||||
return isObject(obj);
|
||||
}
|
||||
|
||||
@ -2,7 +2,9 @@ import { isValidElement } from 'react';
|
||||
import { isReactComponent } from '../is-react';
|
||||
import { IPublicTypeCustomView } from '@alilc/lowcode-types';
|
||||
|
||||
|
||||
export function isCustomView(obj: any): obj is IPublicTypeCustomView {
|
||||
return obj && (isValidElement(obj) || isReactComponent(obj));
|
||||
if (!obj) {
|
||||
return false;
|
||||
}
|
||||
return isValidElement(obj) || isReactComponent(obj);
|
||||
}
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
import { IPublicEnumDragObjectType } from '@alilc/lowcode-types';
|
||||
import { isObject } from '../is-object';
|
||||
|
||||
export function isDragAnyObject(obj: any): boolean {
|
||||
return obj && obj.type !== IPublicEnumDragObjectType.NodeData && obj.type !== IPublicEnumDragObjectType.Node;
|
||||
if (!isObject(obj)) {
|
||||
return false;
|
||||
}
|
||||
return obj.type !== IPublicEnumDragObjectType.NodeData && obj.type !== IPublicEnumDragObjectType.Node;
|
||||
}
|
||||
@ -1,5 +1,9 @@
|
||||
import { IPublicEnumDragObjectType, IPublicTypeDragNodeDataObject } from '@alilc/lowcode-types';
|
||||
import { isObject } from '../is-object';
|
||||
|
||||
export function isDragNodeDataObject(obj: any): obj is IPublicTypeDragNodeDataObject {
|
||||
return obj && obj.type === IPublicEnumDragObjectType.NodeData;
|
||||
if (!isObject(obj)) {
|
||||
return false;
|
||||
}
|
||||
return obj.type === IPublicEnumDragObjectType.NodeData;
|
||||
}
|
||||
@ -1,5 +1,9 @@
|
||||
import { IPublicEnumDragObjectType, IPublicModelNode, IPublicTypeDragNodeObject } from '@alilc/lowcode-types';
|
||||
import { isObject } from '../is-object';
|
||||
|
||||
export function isDragNodeObject<Node = IPublicModelNode>(obj: any): obj is IPublicTypeDragNodeObject<Node> {
|
||||
return obj && obj.type === IPublicEnumDragObjectType.Node;
|
||||
if (!isObject(obj)) {
|
||||
return false;
|
||||
}
|
||||
return obj.type === IPublicEnumDragObjectType.Node;
|
||||
}
|
||||
@ -1,7 +1,10 @@
|
||||
import { isFunction } from '../is-function';
|
||||
import { isReactClass } from '../is-react';
|
||||
import { IPublicTypeDynamicSetter } from '@alilc/lowcode-types';
|
||||
|
||||
|
||||
export function isDynamicSetter(obj: any): obj is IPublicTypeDynamicSetter {
|
||||
return obj && typeof obj === 'function' && !isReactClass(obj);
|
||||
if (!isFunction(obj)) {
|
||||
return false;
|
||||
}
|
||||
return !isReactClass(obj);
|
||||
}
|
||||
|
||||
3
packages/utils/src/check-types/is-function.ts
Normal file
3
packages/utils/src/check-types/is-function.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export function isFunction(obj: any): obj is Function {
|
||||
return obj && typeof obj === 'function';
|
||||
}
|
||||
@ -1,8 +1,9 @@
|
||||
|
||||
// type checks
|
||||
|
||||
import { IPublicTypeI18nData } from "@alilc/lowcode-types";
|
||||
import { IPublicTypeI18nData } from '@alilc/lowcode-types';
|
||||
import { isObject } from '../is-object';
|
||||
|
||||
export function isI18nData(obj: any): obj is IPublicTypeI18nData {
|
||||
return obj && obj.type === 'i18n';
|
||||
if (!isObject(obj)) {
|
||||
return false;
|
||||
}
|
||||
return obj.type === 'i18n';
|
||||
}
|
||||
|
||||
@ -1,10 +1,26 @@
|
||||
import { IPublicTypeJSFunction } from '@alilc/lowcode-types';
|
||||
import { isObject } from '../is-object';
|
||||
|
||||
interface InnerJsFunction {
|
||||
type: 'JSExpression';
|
||||
source: string;
|
||||
value: string;
|
||||
extType: 'function';
|
||||
}
|
||||
|
||||
/**
|
||||
* 内部版本 的 { type: 'JSExpression', source: '', value: '', extType: 'function' } 能力上等同于 JSFunction
|
||||
*/
|
||||
export function isInnerJsFunction(data: any) {
|
||||
return data && data.type === 'JSExpression' && data.extType === 'function';
|
||||
export function isInnerJsFunction(data: any): data is InnerJsFunction {
|
||||
if (!isObject(data)) {
|
||||
return false;
|
||||
}
|
||||
return data.type === 'JSExpression' && data.extType === 'function';
|
||||
}
|
||||
|
||||
export function isJSFunction(data: any): boolean {
|
||||
return typeof data === 'object' && data && data.type === 'JSFunction' || isInnerJsFunction(data);
|
||||
export function isJSFunction(data: any): data is IPublicTypeJSFunction {
|
||||
if (!isObject(data)) {
|
||||
return false;
|
||||
}
|
||||
return data.type === 'JSFunction' || isInnerJsFunction(data);
|
||||
}
|
||||
|
||||
@ -1,4 +1,9 @@
|
||||
import { IPublicTypeJSBlock } from '@alilc/lowcode-types';
|
||||
import { isObject } from '../is-object';
|
||||
|
||||
export function isJSBlock(data: any): boolean {
|
||||
return data && data.type === 'JSBlock';
|
||||
export function isJSBlock(data: any): data is IPublicTypeJSBlock {
|
||||
if (!isObject(data)) {
|
||||
return false;
|
||||
}
|
||||
return data.type === 'JSBlock';
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { IPublicTypeJSExpression } from '@alilc/lowcode-types';
|
||||
import { isObject } from '../is-object';
|
||||
|
||||
/**
|
||||
* 为了避免把 { type: 'JSExpression', extType: 'function' } 误判为表达式,故增加如下逻辑。
|
||||
@ -11,5 +12,8 @@ import { IPublicTypeJSExpression } from '@alilc/lowcode-types';
|
||||
* @returns
|
||||
*/
|
||||
export function isJSExpression(data: any): data is IPublicTypeJSExpression {
|
||||
return data && data.type === 'JSExpression' && data.extType !== 'function';
|
||||
if (!isObject(data)) {
|
||||
return false;
|
||||
}
|
||||
return data.type === 'JSExpression' && data.extType !== 'function';
|
||||
}
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
import { IPublicTypeJSSlot } from '@alilc/lowcode-types';
|
||||
import { isObject } from '../is-object';
|
||||
|
||||
export function isJSSlot(data: any): data is IPublicTypeJSSlot {
|
||||
return data && data.type === 'JSSlot';
|
||||
if (!isObject(data)) {
|
||||
return false;
|
||||
}
|
||||
return data.type === 'JSSlot';
|
||||
}
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
import { IPublicTypeLocationChildrenDetail, IPublicTypeLocationDetailType } from '@alilc/lowcode-types';
|
||||
import { isObject } from '../is-object';
|
||||
|
||||
export function isLocationChildrenDetail(obj: any): obj is IPublicTypeLocationChildrenDetail {
|
||||
return obj && obj.type === IPublicTypeLocationDetailType.Children;
|
||||
if (!isObject(obj)) {
|
||||
return false;
|
||||
}
|
||||
return obj.type === IPublicTypeLocationDetailType.Children;
|
||||
}
|
||||
@ -1,5 +1,9 @@
|
||||
import { IPublicTypeLocationData } from '@alilc/lowcode-types';
|
||||
import { isObject } from '../is-object';
|
||||
|
||||
export function isLocationData(obj: any): obj is IPublicTypeLocationData {
|
||||
return obj && obj.target && obj.detail;
|
||||
if (!isObject(obj)) {
|
||||
return false;
|
||||
}
|
||||
return 'target' in obj && 'detail' in obj;
|
||||
}
|
||||
@ -1,6 +1,15 @@
|
||||
import { IPublicTypeComponentSchema, IPublicTypeProjectSchema } from "@alilc/lowcode-types";
|
||||
import { isComponentSchema } from "./is-component-schema";
|
||||
import { IPublicTypeComponentSchema, IPublicTypeProjectSchema } from '@alilc/lowcode-types';
|
||||
import { isComponentSchema } from './is-component-schema';
|
||||
import { isObject } from '../is-object';
|
||||
|
||||
export function isLowcodeProjectSchema(data: any): data is IPublicTypeProjectSchema<IPublicTypeComponentSchema> {
|
||||
return data && data.componentsTree && data.componentsTree.length && isComponentSchema(data.componentsTree[0]);
|
||||
if (!isObject(data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!('componentsTree' in data) || data.componentsTree.length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isComponentSchema(data.componentsTree[0]);
|
||||
}
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
import { IPublicTypeNodeSchema } from '@alilc/lowcode-types';
|
||||
import { isObject } from '../is-object';
|
||||
|
||||
export function isNodeSchema(data: any): data is IPublicTypeNodeSchema {
|
||||
return data && data.componentName && !data.isNode;
|
||||
if (!isObject(data)) {
|
||||
return false;
|
||||
}
|
||||
return 'componentName' in data && !data.isNode;
|
||||
}
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
import { IPublicModelNode } from '@alilc/lowcode-types';
|
||||
import { isObject } from '../is-object';
|
||||
|
||||
export function isNode<Node = IPublicModelNode>(node: any): node is Node {
|
||||
return node && node.isNode;
|
||||
if (!isObject(node)) {
|
||||
return false;
|
||||
}
|
||||
return node.isNode;
|
||||
}
|
||||
3
packages/utils/src/check-types/is-object.ts
Normal file
3
packages/utils/src/check-types/is-object.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export function isObject(obj: any): boolean {
|
||||
return obj && typeof obj === 'object';
|
||||
}
|
||||
@ -1,6 +1,10 @@
|
||||
import { IPublicTypeComponentMap, IPublicTypeProCodeComponent } from '@alilc/lowcode-types';
|
||||
|
||||
import { isObject } from '../is-object';
|
||||
|
||||
export function isProCodeComponentType(desc: IPublicTypeComponentMap): desc is IPublicTypeProCodeComponent {
|
||||
if (!isObject(desc)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return 'package' in desc;
|
||||
}
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
import { IPublicTypeProjectSchema } from "@alilc/lowcode-types";
|
||||
import { IPublicTypeProjectSchema } from '@alilc/lowcode-types';
|
||||
import { isObject } from '../is-object';
|
||||
|
||||
export function isProjectSchema(data: any): data is IPublicTypeProjectSchema {
|
||||
return data && data.componentsTree;
|
||||
if (!isObject(data)) {
|
||||
return false;
|
||||
}
|
||||
return 'componentsTree' in data;
|
||||
}
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
import { IPublicTypeSetterConfig } from '@alilc/lowcode-types';
|
||||
import { isCustomView } from './is-custom-view';
|
||||
|
||||
import { isObject } from '../is-object';
|
||||
|
||||
export function isSetterConfig(obj: any): obj is IPublicTypeSetterConfig {
|
||||
return obj && typeof obj === 'object' && 'componentName' in obj && !isCustomView(obj);
|
||||
if (!isObject(obj)) {
|
||||
return false;
|
||||
}
|
||||
return 'componentName' in obj && !isCustomView(obj);
|
||||
}
|
||||
|
||||
@ -1,5 +1,10 @@
|
||||
import { IPublicModelSettingField } from "@alilc/lowcode-types";
|
||||
import { IPublicModelSettingField } from '@alilc/lowcode-types';
|
||||
import { isObject } from '../is-object';
|
||||
|
||||
export function isSettingField(obj: any): obj is IPublicModelSettingField {
|
||||
return obj && obj.isSettingField;
|
||||
if (!isObject(obj)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return 'isSettingField' in obj && obj.isSettingField;
|
||||
}
|
||||
|
||||
@ -11,8 +11,8 @@ const excludePropertyNames = [
|
||||
'arguments',
|
||||
];
|
||||
|
||||
export function cloneEnumerableProperty(target: any, origin: any) {
|
||||
const compExtraPropertyNames = Object.keys(origin).filter(d => !excludePropertyNames.includes(d));
|
||||
export function cloneEnumerableProperty(target: any, origin: any, excludes = excludePropertyNames) {
|
||||
const compExtraPropertyNames = Object.keys(origin).filter(d => !excludes.includes(d));
|
||||
|
||||
compExtraPropertyNames.forEach((d: string) => {
|
||||
(target as any)[d] = origin[d];
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
export function isObject(value: any): value is Record<string, unknown> {
|
||||
export function isObject(value: any): value is Record<string, any> {
|
||||
return value !== null && typeof value === 'object';
|
||||
}
|
||||
|
||||
|
||||
@ -2,27 +2,49 @@ import { ComponentClass, Component, FunctionComponent, ComponentType, createElem
|
||||
import { cloneEnumerableProperty } from './clone-enumerable-property';
|
||||
|
||||
const hasSymbol = typeof Symbol === 'function' && Symbol.for;
|
||||
const REACT_FORWARD_REF_TYPE = hasSymbol ? Symbol.for('react.forward_ref') : 0xead0;
|
||||
const REACT_MEMO_TYPE = hasSymbol ? Symbol.for('react.memo') : 0xead3;
|
||||
export const REACT_FORWARD_REF_TYPE = hasSymbol ? Symbol.for('react.forward_ref') : 0xead0;
|
||||
export const REACT_MEMO_TYPE = hasSymbol ? Symbol.for('react.memo') : 0xead3;
|
||||
|
||||
export function isReactClass(obj: any): obj is ComponentClass<any> {
|
||||
return obj && obj.prototype && (obj.prototype.isReactComponent || obj.prototype instanceof Component);
|
||||
if (!obj) {
|
||||
return false;
|
||||
}
|
||||
if (obj.prototype && (obj.prototype.isReactComponent || obj.prototype instanceof Component)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function acceptsRef(obj: any): boolean {
|
||||
return obj?.prototype?.isReactComponent || isForwardOrMemoForward(obj);
|
||||
if (!obj) {
|
||||
return false;
|
||||
}
|
||||
if (obj?.prototype?.isReactComponent || isForwardOrMemoForward(obj)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
export function isForwardRefType(obj: any): boolean {
|
||||
return obj?.$$typeof && obj?.$$typeof === REACT_FORWARD_REF_TYPE;
|
||||
if (!obj || !obj?.$$typeof) {
|
||||
return false;
|
||||
}
|
||||
return obj?.$$typeof === REACT_FORWARD_REF_TYPE;
|
||||
}
|
||||
|
||||
function isMemoType(obj: any): boolean {
|
||||
return obj?.$$typeof && obj.$$typeof === REACT_MEMO_TYPE;
|
||||
export function isMemoType(obj: any): boolean {
|
||||
if (!obj || !obj?.$$typeof) {
|
||||
return false;
|
||||
}
|
||||
return obj.$$typeof === REACT_MEMO_TYPE;
|
||||
}
|
||||
|
||||
export function isForwardOrMemoForward(obj: any): boolean {
|
||||
return obj?.$$typeof && (
|
||||
if (!obj || !obj?.$$typeof) {
|
||||
return false;
|
||||
}
|
||||
return (
|
||||
// React.forwardRef(..)
|
||||
isForwardRefType(obj) ||
|
||||
// React.memo(React.forwardRef(..))
|
||||
|
||||
@ -88,7 +88,7 @@ const shouldOutput = (
|
||||
|
||||
const output = (logLevel: string, bizName: string) => {
|
||||
return (...args: any[]) => {
|
||||
return outputFunction[logLevel].apply(console, getLogArgs(args, bizName, logLevel));
|
||||
return outputFunction[logLevel]?.apply(console, getLogArgs(args, bizName, logLevel));
|
||||
};
|
||||
};
|
||||
|
||||
@ -142,7 +142,6 @@ const defaultOptions: Options = {
|
||||
bizName: '*',
|
||||
};
|
||||
|
||||
|
||||
class Logger {
|
||||
bizName: string;
|
||||
targetBizName: string;
|
||||
@ -192,7 +191,6 @@ class Logger {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export { Logger };
|
||||
|
||||
export function getLogger(config: { level: Level; bizName: string }): Logger {
|
||||
|
||||
@ -2,6 +2,9 @@
|
||||
import { isI18NObject } from './is-object';
|
||||
import { get } from 'lodash';
|
||||
import { IPublicEnumTransformStage, IPublicModelComponentMeta } from '@alilc/lowcode-types';
|
||||
import { Logger } from './logger';
|
||||
|
||||
const logger = new Logger({ level: 'warn', bizName: 'utils' });
|
||||
|
||||
interface Variable {
|
||||
type: 'variable';
|
||||
@ -10,7 +13,10 @@ interface Variable {
|
||||
}
|
||||
|
||||
export function isVariable(obj: any): obj is Variable {
|
||||
return obj && obj.type === 'variable';
|
||||
if (!obj || typeof obj !== 'object') {
|
||||
return false;
|
||||
}
|
||||
return obj.type === 'variable';
|
||||
}
|
||||
|
||||
export function isUseI18NSetter(prototype: any, propName: string) {
|
||||
@ -103,12 +109,15 @@ export function invariant(check: any, message: string, thing?: any) {
|
||||
|
||||
export function deprecate(fail: any, message: string, alterative?: string) {
|
||||
if (fail) {
|
||||
console.warn(`Deprecation: ${message}` + (alterative ? `, use ${alterative} instead.` : ''));
|
||||
logger.warn(`Deprecation: ${message}` + (alterative ? `, use ${alterative} instead.` : ''));
|
||||
}
|
||||
}
|
||||
|
||||
export function isRegExp(obj: any): obj is RegExp {
|
||||
return obj && obj.test && obj.exec && obj.compile;
|
||||
if (!obj || typeof obj !== 'object') {
|
||||
return false;
|
||||
}
|
||||
return 'test' in obj && 'exec' in obj && 'compile' in obj;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
let nativeSelectionEnabled = true;
|
||||
export let nativeSelectionEnabled = true;
|
||||
|
||||
const preventSelection = (e: Event) => {
|
||||
if (nativeSelectionEnabled) {
|
||||
return null;
|
||||
|
||||
@ -1,4 +1,7 @@
|
||||
import { createDefer } from './create-defer';
|
||||
import { Logger } from './logger';
|
||||
|
||||
const logger = new Logger({ level: 'warn', bizName: 'utils' });
|
||||
|
||||
export function evaluate(script: string, scriptType?: string) {
|
||||
const scriptEl = document.createElement('script');
|
||||
@ -53,7 +56,7 @@ export function newFunction(args: string, code: string) {
|
||||
// eslint-disable-next-line no-new-func
|
||||
return new Function(args, code);
|
||||
} catch (e) {
|
||||
console.warn('Caught error, Cant init func');
|
||||
logger.warn('Caught error, Cant init func');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { ReactNode } from 'react';
|
||||
import React, { ReactNode } from 'react';
|
||||
|
||||
const SizePresets: any = {
|
||||
xsmall: 8,
|
||||
|
||||
10
packages/utils/test/src/__snapshots__/is-react.test.tsx.snap
Normal file
10
packages/utils/test/src/__snapshots__/is-react.test.tsx.snap
Normal file
@ -0,0 +1,10 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`wrapReactClass should render the FunctionComponent with props 1`] = `
|
||||
<FunctionComponent
|
||||
prop1="value1"
|
||||
prop2="value2"
|
||||
>
|
||||
Child Text
|
||||
</FunctionComponent>
|
||||
`;
|
||||
@ -1,342 +0,0 @@
|
||||
|
||||
import { buildComponents } from "../../../src/build-components";
|
||||
|
||||
function Button() {};
|
||||
|
||||
function WrapButton() {};
|
||||
|
||||
function ButtonGroup() {};
|
||||
|
||||
function WrapButtonGroup() {};
|
||||
|
||||
ButtonGroup.Button = Button;
|
||||
|
||||
Button.displayName = "Button";
|
||||
ButtonGroup.displayName = "ButtonGroup";
|
||||
ButtonGroup.prototype.isReactComponent = true;
|
||||
Button.prototype.isReactComponent = true;
|
||||
|
||||
jest.mock('../../../src/is-react', () => {
|
||||
const original = jest.requireActual('../../../src/is-react');
|
||||
return {
|
||||
...original,
|
||||
wrapReactClass(view) {
|
||||
return view;
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
describe('build-component', () => {
|
||||
it('basic button', () => {
|
||||
expect(
|
||||
buildComponents(
|
||||
{
|
||||
'@alilc/button': {
|
||||
Button,
|
||||
}
|
||||
},
|
||||
{
|
||||
Button: {
|
||||
componentName: 'Button',
|
||||
package: '@alilc/button',
|
||||
destructuring: true,
|
||||
exportName: 'Button',
|
||||
subName: 'Button',
|
||||
}
|
||||
},
|
||||
() => {},
|
||||
))
|
||||
.toEqual({
|
||||
Button,
|
||||
});
|
||||
});
|
||||
|
||||
it('component is a __esModule', () => {
|
||||
expect(
|
||||
buildComponents(
|
||||
{
|
||||
'@alilc/button': {
|
||||
__esModule: true,
|
||||
default: Button,
|
||||
}
|
||||
},
|
||||
{
|
||||
Button: {
|
||||
componentName: 'Button',
|
||||
package: '@alilc/button',
|
||||
}
|
||||
},
|
||||
() => {},
|
||||
))
|
||||
.toEqual({
|
||||
Button,
|
||||
});
|
||||
})
|
||||
|
||||
it('basic warp button', () => {
|
||||
expect(
|
||||
buildComponents(
|
||||
{
|
||||
'@alilc/button': {
|
||||
WrapButton,
|
||||
}
|
||||
},
|
||||
{
|
||||
WrapButton: {
|
||||
componentName: 'WrapButton',
|
||||
package: '@alilc/button',
|
||||
destructuring: true,
|
||||
exportName: 'WrapButton',
|
||||
subName: 'WrapButton',
|
||||
}
|
||||
},
|
||||
() => {},
|
||||
))
|
||||
.toEqual({
|
||||
WrapButton,
|
||||
});
|
||||
});
|
||||
|
||||
it('destructuring is false button', () => {
|
||||
expect(
|
||||
buildComponents(
|
||||
{
|
||||
'@alilc/button': Button
|
||||
},
|
||||
{
|
||||
Button: {
|
||||
componentName: 'Button',
|
||||
package: '@alilc/button',
|
||||
destructuring: false,
|
||||
}
|
||||
},
|
||||
() => {},
|
||||
))
|
||||
.toEqual({
|
||||
Button,
|
||||
});
|
||||
});
|
||||
|
||||
it('Button and ButtonGroup', () => {
|
||||
expect(
|
||||
buildComponents(
|
||||
{
|
||||
'@alilc/button': {
|
||||
Button,
|
||||
ButtonGroup,
|
||||
}
|
||||
},
|
||||
{
|
||||
Button: {
|
||||
componentName: 'Button',
|
||||
package: '@alilc/button',
|
||||
destructuring: true,
|
||||
exportName: 'Button',
|
||||
subName: 'Button',
|
||||
},
|
||||
ButtonGroup: {
|
||||
componentName: 'ButtonGroup',
|
||||
package: '@alilc/button',
|
||||
destructuring: true,
|
||||
exportName: 'ButtonGroup',
|
||||
subName: 'ButtonGroup',
|
||||
}
|
||||
},
|
||||
() => {},
|
||||
))
|
||||
.toEqual({
|
||||
Button,
|
||||
ButtonGroup,
|
||||
});
|
||||
});
|
||||
|
||||
it('ButtonGroup and ButtonGroup.Button', () => {
|
||||
expect(
|
||||
buildComponents(
|
||||
{
|
||||
'@alilc/button': {
|
||||
ButtonGroup,
|
||||
}
|
||||
},
|
||||
{
|
||||
Button: {
|
||||
componentName: 'Button',
|
||||
package: '@alilc/button',
|
||||
destructuring: true,
|
||||
exportName: 'ButtonGroup',
|
||||
subName: 'ButtonGroup.Button',
|
||||
},
|
||||
ButtonGroup: {
|
||||
componentName: 'ButtonGroup',
|
||||
package: '@alilc/button',
|
||||
destructuring: true,
|
||||
exportName: 'ButtonGroup',
|
||||
subName: 'ButtonGroup',
|
||||
}
|
||||
},
|
||||
() => {},
|
||||
))
|
||||
.toEqual({
|
||||
Button,
|
||||
ButtonGroup,
|
||||
});
|
||||
});
|
||||
|
||||
it('ButtonGroup.default and ButtonGroup.Button', () => {
|
||||
expect(
|
||||
buildComponents(
|
||||
{
|
||||
'@alilc/button': ButtonGroup,
|
||||
},
|
||||
{
|
||||
Button: {
|
||||
componentName: 'Button',
|
||||
package: '@alilc/button',
|
||||
destructuring: true,
|
||||
exportName: 'Button',
|
||||
subName: 'Button',
|
||||
},
|
||||
ButtonGroup: {
|
||||
componentName: 'ButtonGroup',
|
||||
package: '@alilc/button',
|
||||
destructuring: true,
|
||||
exportName: 'default',
|
||||
subName: 'default',
|
||||
}
|
||||
},
|
||||
() => {},
|
||||
))
|
||||
.toEqual({
|
||||
Button,
|
||||
ButtonGroup,
|
||||
});
|
||||
});
|
||||
|
||||
it('no npm component', () => {
|
||||
expect(
|
||||
buildComponents(
|
||||
{
|
||||
'@alilc/button': Button,
|
||||
},
|
||||
{
|
||||
Button: null,
|
||||
},
|
||||
() => {},
|
||||
))
|
||||
.toEqual({});
|
||||
});
|
||||
|
||||
it('no npm component and global button', () => {
|
||||
window.Button = Button;
|
||||
expect(
|
||||
buildComponents(
|
||||
{},
|
||||
{
|
||||
Button: null,
|
||||
},
|
||||
() => {},
|
||||
))
|
||||
.toEqual({
|
||||
Button,
|
||||
});
|
||||
window.Button = null;
|
||||
});
|
||||
|
||||
it('componentsMap value is component funtion', () => {
|
||||
expect(
|
||||
buildComponents(
|
||||
{},
|
||||
{
|
||||
Button,
|
||||
},
|
||||
() => {},
|
||||
))
|
||||
.toEqual({
|
||||
Button,
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('componentsMap value is component', () => {
|
||||
expect(
|
||||
buildComponents(
|
||||
{},
|
||||
{
|
||||
Button: WrapButton,
|
||||
},
|
||||
() => {},
|
||||
))
|
||||
.toEqual({
|
||||
Button: WrapButton,
|
||||
});
|
||||
});
|
||||
|
||||
it('componentsMap value is mix component', () => {
|
||||
expect(
|
||||
buildComponents(
|
||||
{},
|
||||
{
|
||||
Button: {
|
||||
WrapButton,
|
||||
Button,
|
||||
ButtonGroup,
|
||||
},
|
||||
},
|
||||
() => {},
|
||||
))
|
||||
.toEqual({
|
||||
Button: {
|
||||
WrapButton,
|
||||
Button,
|
||||
ButtonGroup,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('componentsMap value is Lowcode Component', () => {
|
||||
expect(
|
||||
buildComponents(
|
||||
{},
|
||||
{
|
||||
Button: {
|
||||
componentName: 'Component',
|
||||
schema: {},
|
||||
},
|
||||
},
|
||||
(component) => {
|
||||
return component as any;
|
||||
},
|
||||
))
|
||||
.toEqual({
|
||||
Button: {
|
||||
componentsMap: [],
|
||||
componentsTree: [
|
||||
{
|
||||
componentName: 'Component',
|
||||
schema: {},
|
||||
}
|
||||
],
|
||||
version: "",
|
||||
},
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
describe('build div component', () => {
|
||||
it('build div component', () => {
|
||||
const components = buildComponents(
|
||||
{
|
||||
'@alilc/div': 'div'
|
||||
},
|
||||
{
|
||||
div: {
|
||||
componentName: 'div',
|
||||
package: '@alilc/div'
|
||||
}
|
||||
},
|
||||
() => {},
|
||||
);
|
||||
|
||||
expect(components['div']).not.toBeNull();
|
||||
})
|
||||
})
|
||||
@ -0,0 +1,616 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
accessLibrary,
|
||||
generateHtmlComp,
|
||||
getSubComponent,
|
||||
buildComponents,
|
||||
getProjectUtils,
|
||||
} from "../../../src/build-components";
|
||||
|
||||
function Button() {};
|
||||
|
||||
function WrapButton() {};
|
||||
|
||||
function ButtonGroup() {};
|
||||
|
||||
function WrapButtonGroup() {};
|
||||
|
||||
ButtonGroup.Button = Button;
|
||||
|
||||
Button.displayName = "Button";
|
||||
ButtonGroup.displayName = "ButtonGroup";
|
||||
ButtonGroup.prototype.isReactComponent = true;
|
||||
Button.prototype.isReactComponent = true;
|
||||
|
||||
jest.mock('../../../src/is-react', () => {
|
||||
const original = jest.requireActual('../../../src/is-react');
|
||||
return {
|
||||
...original,
|
||||
wrapReactClass(view) {
|
||||
return view;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
describe('accessLibrary', () => {
|
||||
it('should return a library object when given a library object', () => {
|
||||
const libraryObject = { key: 'value' };
|
||||
const result = accessLibrary(libraryObject);
|
||||
expect(result).toEqual(libraryObject);
|
||||
});
|
||||
|
||||
it('should generate an HTML component when given a string library name', () => {
|
||||
const libraryName = 'div';
|
||||
const result = accessLibrary(libraryName);
|
||||
|
||||
// You can write more specific assertions to validate the generated component
|
||||
expect(result).toBeDefined();
|
||||
});
|
||||
|
||||
// Add more test cases to cover other scenarios
|
||||
});
|
||||
|
||||
describe('generateHtmlComp', () => {
|
||||
it('should generate an HTML component for valid HTML tags', () => {
|
||||
const htmlTags = ['a', 'img', 'div', 'span', 'svg'];
|
||||
htmlTags.forEach((tag) => {
|
||||
const result = generateHtmlComp(tag);
|
||||
|
||||
// You can write more specific assertions to validate the generated component
|
||||
expect(result).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return undefined for an invalid HTML tag', () => {
|
||||
const invalidTag = 'invalidtag';
|
||||
const result = generateHtmlComp(invalidTag);
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
|
||||
// Add more test cases to cover other scenarios
|
||||
});
|
||||
|
||||
describe('getSubComponent', () => {
|
||||
it('should return the root library if paths are empty', () => {
|
||||
const library = { component: 'RootComponent' };
|
||||
const paths = [];
|
||||
const result = getSubComponent(library, paths);
|
||||
expect(result).toEqual(library);
|
||||
});
|
||||
|
||||
it('should return the specified sub-component', () => {
|
||||
const library = {
|
||||
components: {
|
||||
Button: 'ButtonComponent',
|
||||
Text: 'TextComponent',
|
||||
},
|
||||
};
|
||||
const paths = ['components', 'Button'];
|
||||
const result = getSubComponent(library, paths);
|
||||
expect(result).toEqual('ButtonComponent');
|
||||
});
|
||||
|
||||
it('should handle missing keys in the path', () => {
|
||||
const library = {
|
||||
components: {
|
||||
Button: 'ButtonComponent',
|
||||
},
|
||||
};
|
||||
const paths = ['components', 'Text'];
|
||||
const result = getSubComponent(library, paths);
|
||||
expect(result).toEqual({
|
||||
Button: 'ButtonComponent',
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle exceptions and return null', () => {
|
||||
const library = 'ButtonComponent';
|
||||
const paths = ['components', 'Button'];
|
||||
// Simulate an exception by providing a non-object in place of 'ButtonComponent'
|
||||
const result = getSubComponent(library, paths);
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it('should handle the "default" key as the first path element', () => {
|
||||
const library = {
|
||||
default: 'DefaultComponent',
|
||||
};
|
||||
const paths = ['default'];
|
||||
const result = getSubComponent(library, paths);
|
||||
expect(result).toEqual('DefaultComponent');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getProjectUtils', () => {
|
||||
it('should return an empty object when given empty metadata and library map', () => {
|
||||
const libraryMap = {};
|
||||
const utilsMetadata = [];
|
||||
const result = getProjectUtils(libraryMap, utilsMetadata);
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
|
||||
it('should return project utilities based on metadata and library map', () => {
|
||||
const libraryMap = {
|
||||
'package1': 'library1',
|
||||
'package2': 'library2',
|
||||
};
|
||||
|
||||
const utilsMetadata = [
|
||||
{
|
||||
name: 'util1',
|
||||
npm: {
|
||||
package: 'package1',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'util2',
|
||||
npm: {
|
||||
package: 'package2',
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
global['library1'] = { name: 'library1' };
|
||||
global['library2'] = { name: 'library2' };
|
||||
|
||||
const result = getProjectUtils(libraryMap, utilsMetadata);
|
||||
|
||||
// Define the expected output based on the mocked accessLibrary
|
||||
const expectedOutput = {
|
||||
'util1': { name: 'library1' },
|
||||
'util2': { name: 'library2' },
|
||||
};
|
||||
|
||||
expect(result).toEqual(expectedOutput);
|
||||
|
||||
global['library1'] = null;
|
||||
global['library1'] = null;
|
||||
});
|
||||
|
||||
it('should handle metadata with destructuring', () => {
|
||||
const libraryMap = {
|
||||
'package1': { destructuring: true, util1: 'library1', util2: 'library2' },
|
||||
};
|
||||
|
||||
const utilsMetadata = [
|
||||
{
|
||||
name: 'util1',
|
||||
npm: {
|
||||
package: 'package1',
|
||||
destructuring: true,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const result = getProjectUtils(libraryMap, utilsMetadata);
|
||||
|
||||
// Define the expected output based on the mocked accessLibrary
|
||||
const expectedOutput = {
|
||||
'util1': 'library1',
|
||||
'util2': 'library2',
|
||||
};
|
||||
|
||||
expect(result).toEqual(expectedOutput);
|
||||
});
|
||||
});
|
||||
|
||||
describe('buildComponents', () => {
|
||||
it('should create components from component map with React components', () => {
|
||||
const libraryMap = {};
|
||||
const componentsMap = {
|
||||
Button: () => <button>Button</button>,
|
||||
Text: () => <p>Text</p>,
|
||||
};
|
||||
|
||||
const createComponent = (schema) => {
|
||||
// Mock createComponent function
|
||||
return schema.componentsTree.map((component) => component.component);
|
||||
};
|
||||
|
||||
const result = buildComponents(libraryMap, componentsMap, createComponent);
|
||||
|
||||
expect(result.Button).toBeDefined();
|
||||
expect(result.Text).toBeDefined();
|
||||
});
|
||||
|
||||
it('should create components from component map with component schemas', () => {
|
||||
const libraryMap = {};
|
||||
const componentsMap = {
|
||||
Button: {
|
||||
componentsTree: [
|
||||
{
|
||||
componentName: 'Component'
|
||||
}
|
||||
]
|
||||
},
|
||||
Text: {
|
||||
componentsTree: [
|
||||
{
|
||||
componentName: 'Component'
|
||||
}
|
||||
]
|
||||
},
|
||||
};
|
||||
|
||||
const createComponent = (schema) => {
|
||||
// Mock createComponent function
|
||||
return schema.componentsTree.map((component) => component.component);
|
||||
};
|
||||
|
||||
const result = buildComponents(libraryMap, componentsMap, createComponent);
|
||||
|
||||
expect(result.Button).toBeDefined();
|
||||
expect(result.Text).toBeDefined();
|
||||
});
|
||||
|
||||
it('should create components from component map with React components and schemas', () => {
|
||||
const libraryMap = {};
|
||||
const componentsMap = {
|
||||
Button: () => <button>Button</button>,
|
||||
Text: {
|
||||
type: 'ComponentSchema',
|
||||
// Add component schema properties here
|
||||
},
|
||||
};
|
||||
|
||||
const createComponent = (schema) => {
|
||||
// Mock createComponent function
|
||||
return schema.componentsTree.map((component) => component.component);
|
||||
};
|
||||
|
||||
const result = buildComponents(libraryMap, componentsMap, createComponent);
|
||||
|
||||
expect(result.Button).toBeDefined();
|
||||
expect(result.Text).toBeDefined();
|
||||
});
|
||||
|
||||
it('should create components from component map with library mappings', () => {
|
||||
const libraryMap = {
|
||||
'libraryName1': 'library1',
|
||||
'libraryName2': 'library2',
|
||||
};
|
||||
const componentsMap = {
|
||||
Button: {
|
||||
package: 'libraryName1',
|
||||
version: '1.0',
|
||||
exportName: 'ButtonComponent',
|
||||
},
|
||||
Text: {
|
||||
package: 'libraryName2',
|
||||
version: '2.0',
|
||||
exportName: 'TextComponent',
|
||||
},
|
||||
};
|
||||
|
||||
const createComponent = (schema) => {
|
||||
// Mock createComponent function
|
||||
return schema.componentsTree.map((component) => component.component);
|
||||
};
|
||||
|
||||
global['library1'] = () => <button>ButtonComponent</button>;
|
||||
global['library2'] = () => () => <p>TextComponent</p>;
|
||||
|
||||
const result = buildComponents(libraryMap, componentsMap, createComponent);
|
||||
|
||||
expect(result.Button).toBeDefined();
|
||||
expect(result.Text).toBeDefined();
|
||||
|
||||
global['library1'] = null;
|
||||
global['library2'] = null;
|
||||
});
|
||||
});
|
||||
|
||||
describe('build-component', () => {
|
||||
it('basic button', () => {
|
||||
expect(
|
||||
buildComponents(
|
||||
{
|
||||
'@alilc/button': {
|
||||
Button,
|
||||
}
|
||||
},
|
||||
{
|
||||
Button: {
|
||||
componentName: 'Button',
|
||||
package: '@alilc/button',
|
||||
destructuring: true,
|
||||
exportName: 'Button',
|
||||
subName: 'Button',
|
||||
}
|
||||
},
|
||||
() => {},
|
||||
))
|
||||
.toEqual({
|
||||
Button,
|
||||
});
|
||||
});
|
||||
|
||||
it('component is a __esModule', () => {
|
||||
expect(
|
||||
buildComponents(
|
||||
{
|
||||
'@alilc/button': {
|
||||
__esModule: true,
|
||||
default: Button,
|
||||
}
|
||||
},
|
||||
{
|
||||
Button: {
|
||||
componentName: 'Button',
|
||||
package: '@alilc/button',
|
||||
}
|
||||
},
|
||||
() => {},
|
||||
))
|
||||
.toEqual({
|
||||
Button,
|
||||
});
|
||||
})
|
||||
|
||||
it('basic warp button', () => {
|
||||
expect(
|
||||
buildComponents(
|
||||
{
|
||||
'@alilc/button': {
|
||||
WrapButton,
|
||||
}
|
||||
},
|
||||
{
|
||||
WrapButton: {
|
||||
componentName: 'WrapButton',
|
||||
package: '@alilc/button',
|
||||
destructuring: true,
|
||||
exportName: 'WrapButton',
|
||||
subName: 'WrapButton',
|
||||
}
|
||||
},
|
||||
() => {},
|
||||
))
|
||||
.toEqual({
|
||||
WrapButton,
|
||||
});
|
||||
});
|
||||
|
||||
it('destructuring is false button', () => {
|
||||
expect(
|
||||
buildComponents(
|
||||
{
|
||||
'@alilc/button': Button
|
||||
},
|
||||
{
|
||||
Button: {
|
||||
componentName: 'Button',
|
||||
package: '@alilc/button',
|
||||
destructuring: false,
|
||||
}
|
||||
},
|
||||
() => {},
|
||||
))
|
||||
.toEqual({
|
||||
Button,
|
||||
});
|
||||
});
|
||||
|
||||
it('Button and ButtonGroup', () => {
|
||||
expect(
|
||||
buildComponents(
|
||||
{
|
||||
'@alilc/button': {
|
||||
Button,
|
||||
ButtonGroup,
|
||||
}
|
||||
},
|
||||
{
|
||||
Button: {
|
||||
componentName: 'Button',
|
||||
package: '@alilc/button',
|
||||
destructuring: true,
|
||||
exportName: 'Button',
|
||||
subName: 'Button',
|
||||
},
|
||||
ButtonGroup: {
|
||||
componentName: 'ButtonGroup',
|
||||
package: '@alilc/button',
|
||||
destructuring: true,
|
||||
exportName: 'ButtonGroup',
|
||||
subName: 'ButtonGroup',
|
||||
}
|
||||
},
|
||||
() => {},
|
||||
))
|
||||
.toEqual({
|
||||
Button,
|
||||
ButtonGroup,
|
||||
});
|
||||
});
|
||||
|
||||
it('ButtonGroup and ButtonGroup.Button', () => {
|
||||
expect(
|
||||
buildComponents(
|
||||
{
|
||||
'@alilc/button': {
|
||||
ButtonGroup,
|
||||
}
|
||||
},
|
||||
{
|
||||
Button: {
|
||||
componentName: 'Button',
|
||||
package: '@alilc/button',
|
||||
destructuring: true,
|
||||
exportName: 'ButtonGroup',
|
||||
subName: 'ButtonGroup.Button',
|
||||
},
|
||||
ButtonGroup: {
|
||||
componentName: 'ButtonGroup',
|
||||
package: '@alilc/button',
|
||||
destructuring: true,
|
||||
exportName: 'ButtonGroup',
|
||||
subName: 'ButtonGroup',
|
||||
}
|
||||
},
|
||||
() => {},
|
||||
))
|
||||
.toEqual({
|
||||
Button,
|
||||
ButtonGroup,
|
||||
});
|
||||
});
|
||||
|
||||
it('ButtonGroup.default and ButtonGroup.Button', () => {
|
||||
expect(
|
||||
buildComponents(
|
||||
{
|
||||
'@alilc/button': ButtonGroup,
|
||||
},
|
||||
{
|
||||
Button: {
|
||||
componentName: 'Button',
|
||||
package: '@alilc/button',
|
||||
destructuring: true,
|
||||
exportName: 'Button',
|
||||
subName: 'Button',
|
||||
},
|
||||
ButtonGroup: {
|
||||
componentName: 'ButtonGroup',
|
||||
package: '@alilc/button',
|
||||
destructuring: true,
|
||||
exportName: 'default',
|
||||
subName: 'default',
|
||||
}
|
||||
},
|
||||
() => {},
|
||||
))
|
||||
.toEqual({
|
||||
Button,
|
||||
ButtonGroup,
|
||||
});
|
||||
});
|
||||
|
||||
it('no npm component', () => {
|
||||
expect(
|
||||
buildComponents(
|
||||
{
|
||||
'@alilc/button': Button,
|
||||
},
|
||||
{
|
||||
Button: null,
|
||||
},
|
||||
() => {},
|
||||
))
|
||||
.toEqual({});
|
||||
});
|
||||
|
||||
it('no npm component and global button', () => {
|
||||
window.Button = Button;
|
||||
expect(
|
||||
buildComponents(
|
||||
{},
|
||||
{
|
||||
Button: null,
|
||||
},
|
||||
() => {},
|
||||
))
|
||||
.toEqual({
|
||||
Button,
|
||||
});
|
||||
window.Button = null;
|
||||
});
|
||||
|
||||
it('componentsMap value is component funtion', () => {
|
||||
expect(
|
||||
buildComponents(
|
||||
{},
|
||||
{
|
||||
Button,
|
||||
},
|
||||
() => {},
|
||||
))
|
||||
.toEqual({
|
||||
Button,
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('componentsMap value is component', () => {
|
||||
expect(
|
||||
buildComponents(
|
||||
{},
|
||||
{
|
||||
Button: WrapButton,
|
||||
},
|
||||
() => {},
|
||||
))
|
||||
.toEqual({
|
||||
Button: WrapButton,
|
||||
});
|
||||
});
|
||||
|
||||
it('componentsMap value is mix component', () => {
|
||||
expect(
|
||||
buildComponents(
|
||||
{},
|
||||
{
|
||||
Button: {
|
||||
WrapButton,
|
||||
Button,
|
||||
ButtonGroup,
|
||||
},
|
||||
},
|
||||
() => {},
|
||||
))
|
||||
.toEqual({
|
||||
Button: {
|
||||
WrapButton,
|
||||
Button,
|
||||
ButtonGroup,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('componentsMap value is Lowcode Component', () => {
|
||||
expect(
|
||||
buildComponents(
|
||||
{},
|
||||
{
|
||||
Button: {
|
||||
componentName: 'Component',
|
||||
schema: {},
|
||||
},
|
||||
},
|
||||
(component) => {
|
||||
return component as any;
|
||||
},
|
||||
))
|
||||
.toEqual({
|
||||
Button: {
|
||||
componentsMap: [],
|
||||
componentsTree: [
|
||||
{
|
||||
componentName: 'Component',
|
||||
schema: {},
|
||||
}
|
||||
],
|
||||
version: "",
|
||||
},
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
describe('build div component', () => {
|
||||
it('build div component', () => {
|
||||
const components = buildComponents(
|
||||
{
|
||||
'@alilc/div': 'div'
|
||||
},
|
||||
{
|
||||
div: {
|
||||
componentName: 'div',
|
||||
package: '@alilc/div'
|
||||
}
|
||||
},
|
||||
() => {},
|
||||
);
|
||||
|
||||
expect(components['div']).not.toBeNull();
|
||||
})
|
||||
})
|
||||
@ -0,0 +1,20 @@
|
||||
import { isActionContentObject } from '../../../src/check-types/is-action-content-object';
|
||||
|
||||
describe('isActionContentObject', () => {
|
||||
test('should return true for an object', () => {
|
||||
const obj = { prop: 'value' };
|
||||
expect(isActionContentObject(obj)).toBe(true);
|
||||
});
|
||||
|
||||
test('should return false for a non-object', () => {
|
||||
expect(isActionContentObject('not an object')).toBe(false);
|
||||
expect(isActionContentObject(123)).toBe(false);
|
||||
expect(isActionContentObject(null)).toBe(false);
|
||||
expect(isActionContentObject(undefined)).toBe(false);
|
||||
});
|
||||
|
||||
test('should return false for an empty object', () => {
|
||||
const obj = {};
|
||||
expect(isActionContentObject(obj)).toBe(true);
|
||||
});
|
||||
});
|
||||
26
packages/utils/test/src/check-types/is-custom-view.test.tsx
Normal file
26
packages/utils/test/src/check-types/is-custom-view.test.tsx
Normal file
@ -0,0 +1,26 @@
|
||||
import React from 'react';
|
||||
import { isCustomView } from '../../../src/check-types/is-custom-view';
|
||||
import { IPublicTypeCustomView } from '@alilc/lowcode-types';
|
||||
|
||||
describe('isCustomView', () => {
|
||||
test('should return true when obj is a valid React element', () => {
|
||||
const obj: IPublicTypeCustomView = <div>Hello, World!</div>;
|
||||
expect(isCustomView(obj)).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when obj is a valid React component', () => {
|
||||
const MyComponent: React.FC = () => <div>Hello, World!</div>;
|
||||
const obj: IPublicTypeCustomView = MyComponent;
|
||||
expect(isCustomView(obj)).toBe(true);
|
||||
});
|
||||
|
||||
test('should return false when obj is null or undefined', () => {
|
||||
expect(isCustomView(null)).toBe(false);
|
||||
expect(isCustomView(undefined)).toBe(false);
|
||||
});
|
||||
|
||||
test('should return false when obj is not a valid React element or component', () => {
|
||||
const obj: IPublicTypeCustomView = 'not a valid object';
|
||||
expect(isCustomView(obj)).toBe(false);
|
||||
});
|
||||
});
|
||||
13
packages/utils/test/src/check-types/is-dom-text.test.ts
Normal file
13
packages/utils/test/src/check-types/is-dom-text.test.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { isDOMText } from '../../../src/check-types/is-dom-text';
|
||||
|
||||
describe('isDOMText', () => {
|
||||
it('should return true when the input is a string', () => {
|
||||
const result = isDOMText('Hello World');
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when the input is not a string', () => {
|
||||
const result = isDOMText(123);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,32 @@
|
||||
import { isDragAnyObject } from '../../../src/check-types/is-drag-any-object';
|
||||
import { IPublicEnumDragObjectType } from '@alilc/lowcode-types';
|
||||
|
||||
describe('isDragAnyObject', () => {
|
||||
it('should return false if obj is null', () => {
|
||||
const result = isDragAnyObject(null);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false if obj is number', () => {
|
||||
const result = isDragAnyObject(2);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false if obj.type is NodeData', () => {
|
||||
const obj = { type: IPublicEnumDragObjectType.NodeData };
|
||||
const result = isDragAnyObject(obj);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false if obj.type is Node', () => {
|
||||
const obj = { type: IPublicEnumDragObjectType.Node };
|
||||
const result = isDragAnyObject(obj);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true if obj.type is anything else', () => {
|
||||
const obj = { type: 'SomeOtherType' };
|
||||
const result = isDragAnyObject(obj);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,29 @@
|
||||
import { IPublicEnumDragObjectType, IPublicTypeDragNodeDataObject } from '@alilc/lowcode-types';
|
||||
import { isDragNodeDataObject } from '../../../src/check-types/is-drag-node-data-object';
|
||||
|
||||
describe('isDragNodeDataObject', () => {
|
||||
test('should return true for valid IPublicTypeDragNodeDataObject', () => {
|
||||
const obj: IPublicTypeDragNodeDataObject = {
|
||||
type: IPublicEnumDragObjectType.NodeData,
|
||||
// 其他属性...
|
||||
};
|
||||
|
||||
expect(isDragNodeDataObject(obj)).toBe(true);
|
||||
});
|
||||
|
||||
test('should return false for invalid IPublicTypeDragNodeDataObject', () => {
|
||||
const obj: any = {
|
||||
type: 'InvalidType',
|
||||
// 其他属性...
|
||||
};
|
||||
|
||||
expect(isDragNodeDataObject(obj)).toBe(false);
|
||||
});
|
||||
|
||||
test('should return false for null or undefined', () => {
|
||||
expect(isDragNodeDataObject(null)).toBe(false);
|
||||
expect(isDragNodeDataObject(undefined)).toBe(false);
|
||||
});
|
||||
|
||||
// 可以添加更多测试用例...
|
||||
});
|
||||
@ -0,0 +1,36 @@
|
||||
import { IPublicEnumDragObjectType } from '@alilc/lowcode-types';
|
||||
import { isDragNodeObject } from '../../../src/check-types/is-drag-node-object';
|
||||
|
||||
describe('isDragNodeObject', () => {
|
||||
it('should return true if the object is of IPublicTypeDragNodeObject type and has type IPublicEnumDragObjectType.Node', () => {
|
||||
const obj = {
|
||||
type: IPublicEnumDragObjectType.Node,
|
||||
//... other properties
|
||||
};
|
||||
|
||||
expect(isDragNodeObject(obj)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false if the object is not of IPublicTypeDragNodeObject type', () => {
|
||||
const obj = {
|
||||
type: IPublicEnumDragObjectType.OtherType,
|
||||
//... other properties
|
||||
};
|
||||
|
||||
expect(isDragNodeObject(obj)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false if the object is of IPublicTypeDragNodeObject type but type is not IPublicEnumDragObjectType.Node', () => {
|
||||
const obj = {
|
||||
type: IPublicEnumDragObjectType.OtherType,
|
||||
//... other properties
|
||||
};
|
||||
|
||||
expect(isDragNodeObject(obj)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false if the object is null or undefined', () => {
|
||||
expect(isDragNodeObject(null)).toBe(false);
|
||||
expect(isDragNodeObject(undefined)).toBe(false);
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,28 @@
|
||||
import { Component } from 'react';
|
||||
import { isDynamicSetter } from '../../../src/check-types/is-dynamic-setter';
|
||||
|
||||
describe('isDynamicSetter', () => {
|
||||
it('returns true if input is a dynamic setter function', () => {
|
||||
const dynamicSetter = (value: any) => {
|
||||
// some implementation
|
||||
};
|
||||
|
||||
expect(isDynamicSetter(dynamicSetter)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('returns false if input is not a dynamic setter function', () => {
|
||||
expect(isDynamicSetter('not a function')).toBeFalsy();
|
||||
expect(isDynamicSetter(null)).toBeFalsy();
|
||||
expect(isDynamicSetter(undefined)).toBeFalsy();
|
||||
expect(isDynamicSetter(2)).toBeFalsy();
|
||||
expect(isDynamicSetter(0)).toBeFalsy();
|
||||
});
|
||||
|
||||
it('returns false if input is a React class', () => {
|
||||
class ReactClass extends Component {
|
||||
// some implementation
|
||||
}
|
||||
|
||||
expect(isDynamicSetter(ReactClass)).toBeFalsy();
|
||||
});
|
||||
});
|
||||
27
packages/utils/test/src/check-types/is-i18n-data.test.ts
Normal file
27
packages/utils/test/src/check-types/is-i18n-data.test.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import { isI18nData } from '../../../src/check-types/is-i18n-data';
|
||||
import { IPublicTypeI18nData } from "@alilc/lowcode-types";
|
||||
|
||||
describe('isI18nData', () => {
|
||||
it('should return true for valid i18n data', () => {
|
||||
const i18nData: IPublicTypeI18nData = {
|
||||
type: 'i18n',
|
||||
// add any other required properties here
|
||||
};
|
||||
|
||||
expect(isI18nData(i18nData)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for invalid i18n data', () => {
|
||||
const invalidData = {
|
||||
type: 'some-other-type',
|
||||
// add any other properties here
|
||||
};
|
||||
|
||||
expect(isI18nData(invalidData)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for undefined or null', () => {
|
||||
expect(isI18nData(undefined)).toBe(false);
|
||||
expect(isI18nData(null)).toBe(false);
|
||||
});
|
||||
});
|
||||
61
packages/utils/test/src/check-types/is-isfunction.test.ts
Normal file
61
packages/utils/test/src/check-types/is-isfunction.test.ts
Normal file
@ -0,0 +1,61 @@
|
||||
import { isInnerJsFunction, isJSFunction } from '../../../src/check-types/is-isfunction';
|
||||
|
||||
describe('isInnerJsFunction', () => {
|
||||
test('should return true for valid input', () => {
|
||||
const data = {
|
||||
type: 'JSExpression',
|
||||
source: '',
|
||||
value: '',
|
||||
extType: 'function'
|
||||
};
|
||||
|
||||
expect(isInnerJsFunction(data)).toBe(true);
|
||||
});
|
||||
|
||||
test('should return false for invalid input', () => {
|
||||
const data = {
|
||||
type: 'JSExpression',
|
||||
source: '',
|
||||
value: '',
|
||||
extType: 'object'
|
||||
};
|
||||
|
||||
expect(isInnerJsFunction(data)).toBe(false);
|
||||
expect(isInnerJsFunction(null)).toBe(false);
|
||||
expect(isInnerJsFunction(undefined)).toBe(false);
|
||||
expect(isInnerJsFunction(1)).toBe(false);
|
||||
expect(isInnerJsFunction(0)).toBe(false);
|
||||
expect(isInnerJsFunction('string')).toBe(false);
|
||||
expect(isInnerJsFunction('')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isJSFunction', () => {
|
||||
test('should return true for valid input', () => {
|
||||
const data = {
|
||||
type: 'JSFunction',
|
||||
};
|
||||
|
||||
expect(isJSFunction(data)).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true for inner js function', () => {
|
||||
const data = {
|
||||
type: 'JSExpression',
|
||||
source: '',
|
||||
value: '',
|
||||
extType: 'function'
|
||||
};
|
||||
|
||||
expect(isJSFunction(data)).toBe(true);
|
||||
});
|
||||
|
||||
test('should return false for invalid input', () => {
|
||||
expect(isJSFunction(null)).toBe(false);
|
||||
expect(isJSFunction(undefined)).toBe(false);
|
||||
expect(isJSFunction('string')).toBe(false);
|
||||
expect(isJSFunction('')).toBe(false);
|
||||
expect(isJSFunction(0)).toBe(false);
|
||||
expect(isJSFunction(2)).toBe(false);
|
||||
});
|
||||
});
|
||||
22
packages/utils/test/src/check-types/is-jsblock.test.ts
Normal file
22
packages/utils/test/src/check-types/is-jsblock.test.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { isJSBlock } from '../../../src/check-types/is-jsblock';
|
||||
|
||||
describe('isJSBlock', () => {
|
||||
it('should return false if data is null or undefined', () => {
|
||||
expect(isJSBlock(null)).toBe(false);
|
||||
expect(isJSBlock(undefined)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false if data is not an object', () => {
|
||||
expect(isJSBlock('JSBlock')).toBe(false);
|
||||
expect(isJSBlock(123)).toBe(false);
|
||||
expect(isJSBlock(true)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false if data.type is not "JSBlock"', () => {
|
||||
expect(isJSBlock({ type: 'InvalidType' })).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true if data is an object and data.type is "JSBlock"', () => {
|
||||
expect(isJSBlock({ type: 'JSBlock' })).toBe(true);
|
||||
});
|
||||
});
|
||||
39
packages/utils/test/src/check-types/is-jsexpression.test.ts
Normal file
39
packages/utils/test/src/check-types/is-jsexpression.test.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import { isJSExpression } from '../../../src/check-types/is-jsexpression';
|
||||
|
||||
describe('isJSExpression', () => {
|
||||
it('should return true if the input is a valid JSExpression object', () => {
|
||||
const validJSExpression = {
|
||||
type: 'JSExpression',
|
||||
extType: 'variable',
|
||||
};
|
||||
|
||||
const result = isJSExpression(validJSExpression);
|
||||
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false if the input is not a valid JSExpression object', () => {
|
||||
const invalidJSExpression = {
|
||||
type: 'JSExpression',
|
||||
extType: 'function',
|
||||
};
|
||||
|
||||
const result = isJSExpression(invalidJSExpression);
|
||||
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false if the input is null', () => {
|
||||
const result = isJSExpression(null);
|
||||
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false if the input is undefined', () => {
|
||||
const result = isJSExpression(undefined);
|
||||
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
// 添加其他需要的测试
|
||||
});
|
||||
37
packages/utils/test/src/check-types/is-jsslot.test.ts
Normal file
37
packages/utils/test/src/check-types/is-jsslot.test.ts
Normal file
@ -0,0 +1,37 @@
|
||||
import { isJSSlot } from '../../../src/check-types/is-jsslot';
|
||||
import { IPublicTypeJSSlot } from '@alilc/lowcode-types';
|
||||
|
||||
describe('isJSSlot', () => {
|
||||
it('should return true when input is of type IPublicTypeJSSlot', () => {
|
||||
const input: IPublicTypeJSSlot = {
|
||||
type: 'JSSlot',
|
||||
// other properties of IPublicTypeJSSlot
|
||||
};
|
||||
|
||||
const result = isJSSlot(input);
|
||||
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when input is not of type IPublicTypeJSSlot', () => {
|
||||
const input = {
|
||||
type: 'OtherType',
|
||||
// other properties
|
||||
};
|
||||
|
||||
const result = isJSSlot(input);
|
||||
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false when input is null or undefined', () => {
|
||||
const input1 = null;
|
||||
const input2 = undefined;
|
||||
|
||||
const result1 = isJSSlot(input1);
|
||||
const result2 = isJSSlot(input2);
|
||||
|
||||
expect(result1).toBe(false);
|
||||
expect(result2).toBe(false);
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,27 @@
|
||||
import { isLocationChildrenDetail } from '../../../src/check-types/is-location-children-detail';
|
||||
import { IPublicTypeLocationChildrenDetail, IPublicTypeLocationDetailType } from '@alilc/lowcode-types';
|
||||
|
||||
describe('isLocationChildrenDetail', () => {
|
||||
it('should return true when obj is IPublicTypeLocationChildrenDetail', () => {
|
||||
const obj: IPublicTypeLocationChildrenDetail = {
|
||||
type: IPublicTypeLocationDetailType.Children,
|
||||
// 添加其他必要的属性
|
||||
};
|
||||
|
||||
expect(isLocationChildrenDetail(obj)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when obj is not IPublicTypeLocationChildrenDetail', () => {
|
||||
const obj = {
|
||||
type: 'other',
|
||||
// 添加其他必要的属性
|
||||
};
|
||||
|
||||
expect(isLocationChildrenDetail(obj)).toBe(false);
|
||||
expect(isLocationChildrenDetail(null)).toBe(false);
|
||||
expect(isLocationChildrenDetail(undefined)).toBe(false);
|
||||
expect(isLocationChildrenDetail('string')).toBe(false);
|
||||
expect(isLocationChildrenDetail(0)).toBe(false);
|
||||
expect(isLocationChildrenDetail(2)).toBe(false);
|
||||
});
|
||||
});
|
||||
44
packages/utils/test/src/check-types/is-location-data.test.ts
Normal file
44
packages/utils/test/src/check-types/is-location-data.test.ts
Normal file
@ -0,0 +1,44 @@
|
||||
import { isLocationData } from '../../../src/check-types/is-location-data';
|
||||
import { IPublicTypeLocationData } from '@alilc/lowcode-types';
|
||||
|
||||
describe('isLocationData', () => {
|
||||
it('should return true when obj is valid location data', () => {
|
||||
const obj: IPublicTypeLocationData = {
|
||||
target: 'some target',
|
||||
detail: 'some detail',
|
||||
};
|
||||
|
||||
const result = isLocationData(obj);
|
||||
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when obj is missing target or detail', () => {
|
||||
const obj1 = {
|
||||
target: 'some target',
|
||||
// missing detail
|
||||
};
|
||||
|
||||
const obj2 = {
|
||||
// missing target
|
||||
detail: 'some detail',
|
||||
};
|
||||
|
||||
const result1 = isLocationData(obj1);
|
||||
const result2 = isLocationData(obj2);
|
||||
|
||||
expect(result1).toBe(false);
|
||||
expect(result2).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false when obj is null or undefined', () => {
|
||||
const obj1 = null;
|
||||
const obj2 = undefined;
|
||||
|
||||
const result1 = isLocationData(obj1);
|
||||
const result2 = isLocationData(obj2);
|
||||
|
||||
expect(result1).toBe(false);
|
||||
expect(result2).toBe(false);
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,21 @@
|
||||
import { isLowCodeComponentType } from '../../../src/check-types/is-lowcode-component-type';
|
||||
import { IPublicTypeLowCodeComponent, IPublicTypeProCodeComponent } from '@alilc/lowcode-types';
|
||||
|
||||
describe('isLowCodeComponentType', () => {
|
||||
test('should return true for a low code component type', () => {
|
||||
const desc: IPublicTypeLowCodeComponent = {
|
||||
// create a valid low code component description
|
||||
};
|
||||
|
||||
expect(isLowCodeComponentType(desc)).toBe(true);
|
||||
});
|
||||
|
||||
test('should return false for a pro code component type', () => {
|
||||
const desc: IPublicTypeProCodeComponent = {
|
||||
// create a valid pro code component description
|
||||
package: 'pro-code'
|
||||
};
|
||||
|
||||
expect(isLowCodeComponentType(desc)).toBe(false);
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,42 @@
|
||||
import { isLowcodeProjectSchema } from "../../../src/check-types/is-lowcode-project-schema";
|
||||
|
||||
describe("isLowcodeProjectSchema", () => {
|
||||
it("should return false when data is null", () => {
|
||||
const result = isLowcodeProjectSchema(null);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it("should return false when data is undefined", () => {
|
||||
const result = isLowcodeProjectSchema(undefined);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it("should return false when data is not an object", () => {
|
||||
const result = isLowcodeProjectSchema("not an object");
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it("should return false when componentsTree is missing", () => {
|
||||
const data = { someKey: "someValue" };
|
||||
const result = isLowcodeProjectSchema(data);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it("should return false when componentsTree is an empty array", () => {
|
||||
const data = { componentsTree: [] };
|
||||
const result = isLowcodeProjectSchema(data);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it("should return false when the first element of componentsTree is not a component schema", () => {
|
||||
const data = { componentsTree: [{}] };
|
||||
const result = isLowcodeProjectSchema(data);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it("should return true when all conditions are met", () => {
|
||||
const data = { componentsTree: [{ prop: "value", componentName: 'Component' }] };
|
||||
const result = isLowcodeProjectSchema(data);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
});
|
||||
43
packages/utils/test/src/check-types/is-node-schema.test.ts
Normal file
43
packages/utils/test/src/check-types/is-node-schema.test.ts
Normal file
@ -0,0 +1,43 @@
|
||||
import { isNodeSchema } from '../../../src/check-types/is-node-schema';
|
||||
|
||||
describe('isNodeSchema', () => {
|
||||
// 测试正常情况
|
||||
it('should return true for valid IPublicTypeNodeSchema', () => {
|
||||
const validData = {
|
||||
componentName: 'Component',
|
||||
isNode: false,
|
||||
};
|
||||
expect(isNodeSchema(validData)).toBe(true);
|
||||
});
|
||||
|
||||
// 测试 null 或 undefined
|
||||
it('should return false for null or undefined', () => {
|
||||
expect(isNodeSchema(null)).toBe(false);
|
||||
expect(isNodeSchema(undefined)).toBe(false);
|
||||
});
|
||||
|
||||
// 测试没有componentName属性的情况
|
||||
it('should return false if componentName is missing', () => {
|
||||
const invalidData = {
|
||||
isNode: false,
|
||||
};
|
||||
expect(isNodeSchema(invalidData)).toBe(false);
|
||||
});
|
||||
|
||||
// 测试isNode为true的情况
|
||||
it('should return false if isNode is true', () => {
|
||||
const invalidData = {
|
||||
componentName: 'Component',
|
||||
isNode: true,
|
||||
};
|
||||
expect(isNodeSchema(invalidData)).toBe(false);
|
||||
});
|
||||
|
||||
// 测试其他数据类型的情况
|
||||
it('should return false for other data types', () => {
|
||||
expect(isNodeSchema('string')).toBe(false);
|
||||
expect(isNodeSchema(123)).toBe(false);
|
||||
expect(isNodeSchema([])).toBe(false);
|
||||
expect(isNodeSchema({})).toBe(false);
|
||||
});
|
||||
});
|
||||
19
packages/utils/test/src/check-types/is-node.test.ts
Normal file
19
packages/utils/test/src/check-types/is-node.test.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { isNode } from '../../../src/check-types/is-node';
|
||||
|
||||
describe('isNode', () => {
|
||||
it('should return true for a valid node', () => {
|
||||
const node = { isNode: true };
|
||||
expect(isNode(node)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should return false for an invalid node', () => {
|
||||
const node = { isNode: false };
|
||||
expect(isNode(node)).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should return false for an undefined node', () => {
|
||||
expect(isNode(undefined)).toBeFalsy();
|
||||
});
|
||||
|
||||
// Add more test cases if needed
|
||||
});
|
||||
@ -0,0 +1,13 @@
|
||||
import { isProCodeComponentType } from '../../../src/check-types/is-procode-component-type';
|
||||
|
||||
describe('isProCodeComponentType', () => {
|
||||
it('should return true if the given desc object contains "package" property', () => {
|
||||
const desc = { package: 'packageName' };
|
||||
expect(isProCodeComponentType(desc)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false if the given desc object does not contain "package" property', () => {
|
||||
const desc = { name: 'componentName' };
|
||||
expect(isProCodeComponentType(desc)).toBe(false);
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,28 @@
|
||||
import { IPublicTypeProjectSchema } from "@alilc/lowcode-types";
|
||||
import { isProjectSchema } from "../../../src/check-types/is-project-schema";
|
||||
|
||||
describe("isProjectSchema", () => {
|
||||
it("should return true if data has componentsTree property", () => {
|
||||
const data: IPublicTypeProjectSchema = {
|
||||
// ...
|
||||
componentsTree: {
|
||||
// ...
|
||||
},
|
||||
};
|
||||
expect(isProjectSchema(data)).toBe(true);
|
||||
});
|
||||
|
||||
it("should return false if data does not have componentsTree property", () => {
|
||||
const data = {
|
||||
// ...
|
||||
};
|
||||
expect(isProjectSchema(data)).toBe(false);
|
||||
});
|
||||
|
||||
it("should return false if data is null or undefined", () => {
|
||||
expect(isProjectSchema(null)).toBe(false);
|
||||
expect(isProjectSchema(undefined)).toBe(false);
|
||||
});
|
||||
|
||||
// 更多的测试用例...
|
||||
});
|
||||
26
packages/utils/test/src/check-types/is-setter-config.test.ts
Normal file
26
packages/utils/test/src/check-types/is-setter-config.test.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import { isSetterConfig } from '../../../src/check-types/is-setter-config';
|
||||
|
||||
describe('isSetterConfig', () => {
|
||||
test('should return true for valid setter config', () => {
|
||||
const config = {
|
||||
componentName: 'MyComponent',
|
||||
// Add other required properties here
|
||||
};
|
||||
|
||||
expect(isSetterConfig(config)).toBe(true);
|
||||
});
|
||||
|
||||
test('should return false for invalid setter config', () => {
|
||||
const config = {
|
||||
// Missing componentName property
|
||||
};
|
||||
|
||||
expect(isSetterConfig(config)).toBe(false);
|
||||
expect(isSetterConfig(null)).toBe(false);
|
||||
expect(isSetterConfig(undefined)).toBe(false);
|
||||
expect(isSetterConfig(0)).toBe(false);
|
||||
expect(isSetterConfig(2)).toBe(false);
|
||||
});
|
||||
|
||||
// Add more test cases for different scenarios you want to cover
|
||||
});
|
||||
18
packages/utils/test/src/check-types/is-setting-field.test.ts
Normal file
18
packages/utils/test/src/check-types/is-setting-field.test.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { isSettingField } from "../../../src/check-types/is-setting-field";
|
||||
|
||||
describe("isSettingField", () => {
|
||||
it("should return true for an object that has isSettingField property", () => {
|
||||
const obj = { isSettingField: true };
|
||||
expect(isSettingField(obj)).toBe(true);
|
||||
});
|
||||
|
||||
it("should return false for an object that does not have isSettingField property", () => {
|
||||
const obj = { foo: "bar" };
|
||||
expect(isSettingField(obj)).toBe(false);
|
||||
});
|
||||
|
||||
it("should return false for a falsy value", () => {
|
||||
const obj = null;
|
||||
expect(isSettingField(obj)).toBe(false);
|
||||
});
|
||||
});
|
||||
18
packages/utils/test/src/check-types/is-title-config.test.ts
Normal file
18
packages/utils/test/src/check-types/is-title-config.test.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { isTitleConfig } from '../../../src/check-types/is-title-config';
|
||||
|
||||
describe('isTitleConfig', () => {
|
||||
it('should return true for valid config object', () => {
|
||||
const config = { title: 'My Title' };
|
||||
expect(isTitleConfig(config)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for invalid config object', () => {
|
||||
const config = { title: 'My Title', type: 'i18n' , i18nData: {} };
|
||||
expect(isTitleConfig(config)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for non-object input', () => {
|
||||
const config = 'invalid';
|
||||
expect(isTitleConfig(config)).toBe(false);
|
||||
});
|
||||
});
|
||||
30
packages/utils/test/src/clone-deep.test.ts
Normal file
30
packages/utils/test/src/clone-deep.test.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import { cloneDeep } from '../../src/clone-deep';
|
||||
|
||||
describe('cloneDeep', () => {
|
||||
it('should clone null', () => {
|
||||
const src = null;
|
||||
expect(cloneDeep(src)).toBeNull();
|
||||
});
|
||||
|
||||
it('should clone undefined', () => {
|
||||
const src = undefined;
|
||||
expect(cloneDeep(src)).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should clone an array', () => {
|
||||
const src = [1, 2, 3, 4];
|
||||
expect(cloneDeep(src)).toEqual(src);
|
||||
});
|
||||
|
||||
it('should clone an object', () => {
|
||||
const src = { name: 'John', age: 25 };
|
||||
expect(cloneDeep(src)).toEqual(src);
|
||||
});
|
||||
|
||||
it('should deep clone nested objects', () => {
|
||||
const src = { person: { name: 'John', age: 25 } };
|
||||
const cloned = cloneDeep(src);
|
||||
expect(cloned).toEqual(src);
|
||||
expect(cloned.person).not.toBe(src.person);
|
||||
});
|
||||
});
|
||||
30
packages/utils/test/src/clone-enumerable-property.test.ts
Normal file
30
packages/utils/test/src/clone-enumerable-property.test.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import { cloneEnumerableProperty } from '../../src/clone-enumerable-property';
|
||||
|
||||
describe('cloneEnumerableProperty', () => {
|
||||
test('should clone enumerable properties from origin to target', () => {
|
||||
// Arrange
|
||||
const target = {};
|
||||
const origin = { prop1: 1, prop2: 'hello', prop3: true };
|
||||
|
||||
// Act
|
||||
const result = cloneEnumerableProperty(target, origin);
|
||||
|
||||
// Assert
|
||||
expect(result).toBe(target);
|
||||
expect(result).toEqual(origin);
|
||||
});
|
||||
|
||||
test('should exclude properties specified in excludePropertyNames', () => {
|
||||
// Arrange
|
||||
const target = {};
|
||||
const origin = { prop1: 1, prop2: 'hello', prop3: true };
|
||||
const excludePropertyNames = ['prop2'];
|
||||
|
||||
// Act
|
||||
const result = cloneEnumerableProperty(target, origin, excludePropertyNames);
|
||||
|
||||
// Assert
|
||||
expect(result).toBe(target);
|
||||
expect(result).toEqual({ prop1: 1, prop3: true });
|
||||
});
|
||||
});
|
||||
38
packages/utils/test/src/create-content.test.tsx
Normal file
38
packages/utils/test/src/create-content.test.tsx
Normal file
@ -0,0 +1,38 @@
|
||||
import React from 'react';
|
||||
import { createContent } from '../../src/create-content';
|
||||
|
||||
const MyComponent = () => {
|
||||
return <div>MyComponent</div>
|
||||
}
|
||||
describe('createContent', () => {
|
||||
test('should return the same content if it is a valid React element', () => {
|
||||
const content = <div>Hello</div>;
|
||||
const result = createContent(content);
|
||||
|
||||
expect(result).toEqual(content);
|
||||
});
|
||||
|
||||
test('should clone the element with props if props are provided', () => {
|
||||
const content = <div></div>;
|
||||
const props = { className: 'my-class' };
|
||||
const result = createContent(content, props);
|
||||
|
||||
expect(result.props).toEqual(props);
|
||||
});
|
||||
|
||||
test('should create an element with props if the content is a React component', () => {
|
||||
const content = MyComponent;
|
||||
const props = { className: 'my-class' };
|
||||
const result = createContent(content, props);
|
||||
|
||||
expect(result.type).toEqual(content);
|
||||
expect(result.props).toEqual(props);
|
||||
});
|
||||
|
||||
test('should return the content if it is not a React element or a React component', () => {
|
||||
const content = 'Hello';
|
||||
const result = createContent(content);
|
||||
|
||||
expect(result).toEqual(content);
|
||||
});
|
||||
});
|
||||
16
packages/utils/test/src/create-defer.test.ts
Normal file
16
packages/utils/test/src/create-defer.test.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { createDefer } from '../../src/create-defer';
|
||||
|
||||
describe('createDefer', () => {
|
||||
it('should resolve with given value', async () => {
|
||||
const defer = createDefer<number>();
|
||||
defer.resolve(42);
|
||||
const result = await defer.promise();
|
||||
expect(result).toBe(42);
|
||||
});
|
||||
|
||||
it('should reject with given reason', async () => {
|
||||
const defer = createDefer<number>();
|
||||
defer.reject('error');
|
||||
await expect(defer.promise()).rejects.toEqual('error');
|
||||
});
|
||||
});
|
||||
45
packages/utils/test/src/is-object.test.ts
Normal file
45
packages/utils/test/src/is-object.test.ts
Normal file
@ -0,0 +1,45 @@
|
||||
import { isObject, isI18NObject } from '../../src/is-object';
|
||||
|
||||
describe('isObject', () => {
|
||||
it('should return true for an object', () => {
|
||||
const obj = { key: 'value' };
|
||||
const result = isObject(obj);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for null', () => {
|
||||
const result = isObject(null);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for a non-object value', () => {
|
||||
const value = 42; // Not an object
|
||||
const result = isObject(value);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isI18NObject', () => {
|
||||
it('should return true for an I18N object', () => {
|
||||
const i18nObject = { type: 'i18n', data: 'some data' };
|
||||
const result = isI18NObject(i18nObject);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for a non-I18N object', () => {
|
||||
const nonI18nObject = { type: 'other', data: 'some data' };
|
||||
const result = isI18NObject(nonI18nObject);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for null', () => {
|
||||
const result = isI18NObject(null);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for a non-object value', () => {
|
||||
const value = 42; // Not an object
|
||||
const result = isI18NObject(value);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
@ -1,38 +0,0 @@
|
||||
import React from "react";
|
||||
import { isReactComponent, wrapReactClass } from "../../src/is-react";
|
||||
|
||||
class reactDemo extends React.Component {
|
||||
|
||||
}
|
||||
|
||||
const reactMemo = React.memo(reactDemo);
|
||||
|
||||
const reactForwardRef = React.forwardRef((props, ref): any => {
|
||||
return '';
|
||||
});
|
||||
|
||||
describe('is-react-ut', () => {
|
||||
it('isReactComponent', () => {
|
||||
expect(isReactComponent(null)).toBeFalsy();
|
||||
expect(isReactComponent(() => {})).toBeTruthy();
|
||||
expect(isReactComponent({
|
||||
$$typeof: Symbol.for('react.memo')
|
||||
})).toBeTruthy();
|
||||
expect(isReactComponent({
|
||||
$$typeof: Symbol.for('react.forward_ref')
|
||||
})).toBeTruthy();
|
||||
expect(isReactComponent(reactDemo)).toBeTruthy();
|
||||
expect(isReactComponent(reactMemo)).toBeTruthy();
|
||||
expect(isReactComponent(reactForwardRef)).toBeTruthy();
|
||||
|
||||
});
|
||||
|
||||
it('wrapReactClass', () => {
|
||||
const wrap = wrapReactClass(() => {});
|
||||
expect(isReactComponent(wrap)).toBeTruthy();
|
||||
|
||||
const fun = () => {};
|
||||
fun.displayName = 'mock';
|
||||
expect(wrapReactClass(fun).displayName).toBe('mock');
|
||||
})
|
||||
})
|
||||
316
packages/utils/test/src/is-react.test.tsx
Normal file
316
packages/utils/test/src/is-react.test.tsx
Normal file
@ -0,0 +1,316 @@
|
||||
import React, { Component, createElement } from "react";
|
||||
import {
|
||||
isReactComponent,
|
||||
wrapReactClass,
|
||||
isForwardOrMemoForward,
|
||||
isMemoType,
|
||||
isForwardRefType,
|
||||
acceptsRef,
|
||||
isReactClass,
|
||||
REACT_MEMO_TYPE,
|
||||
REACT_FORWARD_REF_TYPE,
|
||||
} from "../../src/is-react";
|
||||
|
||||
class reactDemo extends React.Component {
|
||||
|
||||
}
|
||||
|
||||
const reactMemo = React.memo(reactDemo);
|
||||
|
||||
const reactForwardRef = React.forwardRef((props, ref): any => {
|
||||
return '';
|
||||
});
|
||||
|
||||
describe('is-react-ut', () => {
|
||||
it('isReactComponent', () => {
|
||||
expect(isReactComponent(null)).toBeFalsy();
|
||||
expect(isReactComponent(() => {})).toBeTruthy();
|
||||
expect(isReactComponent({
|
||||
$$typeof: Symbol.for('react.memo')
|
||||
})).toBeTruthy();
|
||||
expect(isReactComponent({
|
||||
$$typeof: Symbol.for('react.forward_ref')
|
||||
})).toBeTruthy();
|
||||
expect(isReactComponent(reactDemo)).toBeTruthy();
|
||||
expect(isReactComponent(reactMemo)).toBeTruthy();
|
||||
expect(isReactComponent(reactForwardRef)).toBeTruthy();
|
||||
|
||||
});
|
||||
|
||||
it('wrapReactClass', () => {
|
||||
const wrap = wrapReactClass(() => {});
|
||||
expect(isReactComponent(wrap)).toBeTruthy();
|
||||
|
||||
const fun = () => {};
|
||||
fun.displayName = 'mock';
|
||||
expect(wrapReactClass(fun).displayName).toBe('mock');
|
||||
})
|
||||
})
|
||||
|
||||
describe('wrapReactClass', () => {
|
||||
it('should wrap a FunctionComponent', () => {
|
||||
// Create a mock FunctionComponent
|
||||
const MockComponent: React.FunctionComponent = (props) => {
|
||||
return <div>{props.children}</div>;
|
||||
};
|
||||
|
||||
// Wrap the FunctionComponent using wrapReactClass
|
||||
const WrappedComponent = wrapReactClass(MockComponent);
|
||||
const instance = new WrappedComponent();
|
||||
|
||||
// Check if the WrappedComponent extends Component
|
||||
expect(instance instanceof React.Component).toBe(true);
|
||||
});
|
||||
|
||||
it('should render the FunctionComponent with props', () => {
|
||||
// Create a mock FunctionComponent
|
||||
const MockComponent: React.FunctionComponent = (props) => {
|
||||
return <div>{props.children}</div>;
|
||||
};
|
||||
|
||||
MockComponent.displayName = 'FunctionComponent';
|
||||
|
||||
// Wrap the FunctionComponent using wrapReactClass
|
||||
const WrappedComponent = wrapReactClass(MockComponent);
|
||||
|
||||
// Create some test props
|
||||
const testProps = { prop1: 'value1', prop2: 'value2' };
|
||||
|
||||
// Render the WrappedComponent with test props
|
||||
const rendered = createElement(WrappedComponent, testProps, 'Child Text');
|
||||
|
||||
// Check if the WrappedComponent renders the FunctionComponent with props
|
||||
expect(rendered).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('isReactComponent', () => {
|
||||
it('should identify a class component as a React component', () => {
|
||||
class ClassComponent extends React.Component {
|
||||
render() {
|
||||
return <div>Class Component</div>;
|
||||
}
|
||||
}
|
||||
|
||||
expect(isReactComponent(ClassComponent)).toBe(true);
|
||||
});
|
||||
|
||||
it('should identify a functional component as a React component', () => {
|
||||
const FunctionalComponent = () => {
|
||||
return <div>Functional Component</div>;
|
||||
};
|
||||
|
||||
expect(isReactComponent(FunctionalComponent)).toBe(true);
|
||||
});
|
||||
|
||||
it('should identify a forward ref component as a React component', () => {
|
||||
const ForwardRefComponent = React.forwardRef((props, ref) => {
|
||||
return <div ref={ref}>Forward Ref Component</div>;
|
||||
});
|
||||
|
||||
expect(isReactComponent(ForwardRefComponent)).toBe(true);
|
||||
});
|
||||
|
||||
it('should identify a memo component as a React component', () => {
|
||||
const MemoComponent = React.memo(() => {
|
||||
return <div>Memo Component</div>;
|
||||
});
|
||||
|
||||
expect(isReactComponent(MemoComponent)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for non-React components', () => {
|
||||
const plainObject = { prop: 'value' };
|
||||
const notAComponent = 'Not a component';
|
||||
|
||||
expect(isReactComponent(plainObject)).toBe(false);
|
||||
expect(isReactComponent(notAComponent)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for null or undefined', () => {
|
||||
const nullValue = null;
|
||||
const undefinedValue = undefined;
|
||||
|
||||
expect(isReactComponent(nullValue)).toBe(false);
|
||||
expect(isReactComponent(undefinedValue)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isForwardOrMemoForward', () => {
|
||||
it('should return true for a forwardRef component', () => {
|
||||
const forwardRefComponent = React.forwardRef(() => {
|
||||
return <div>ForwardRef Component</div>;
|
||||
});
|
||||
|
||||
expect(isForwardOrMemoForward(forwardRefComponent)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true for a memoized forwardRef component', () => {
|
||||
const forwardRefComponent = React.forwardRef(() => {
|
||||
return <div>ForwardRef Component</div>;
|
||||
});
|
||||
|
||||
const memoizedComponent = React.memo(forwardRefComponent);
|
||||
|
||||
expect(isForwardOrMemoForward(memoizedComponent)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for a memoized component that is not a forwardRef', () => {
|
||||
const memoizedComponent = React.memo(() => {
|
||||
return <div>Memoized Component</div>;
|
||||
});
|
||||
|
||||
expect(isForwardOrMemoForward(memoizedComponent)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for a plain object', () => {
|
||||
const plainObject = { prop: 'value' };
|
||||
|
||||
expect(isForwardOrMemoForward(plainObject)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for null or undefined', () => {
|
||||
const nullValue = null;
|
||||
const undefinedValue = undefined;
|
||||
|
||||
expect(isForwardOrMemoForward(nullValue)).toBe(false);
|
||||
expect(isForwardOrMemoForward(undefinedValue)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isMemoType', () => {
|
||||
it('should return true for an object with $$typeof matching REACT_MEMO_TYPE', () => {
|
||||
const memoTypeObject = { $$typeof: REACT_MEMO_TYPE };
|
||||
|
||||
expect(isMemoType(memoTypeObject)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for an object with $$typeof not matching REACT_MEMO_TYPE', () => {
|
||||
const otherTypeObject = { $$typeof: Symbol.for('other.type') };
|
||||
|
||||
expect(isMemoType(otherTypeObject)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for an object with no $$typeof property', () => {
|
||||
const noTypeObject = { key: 'value' };
|
||||
|
||||
expect(isMemoType(noTypeObject)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for null or undefined', () => {
|
||||
const nullValue = null;
|
||||
const undefinedValue = undefined;
|
||||
|
||||
expect(isMemoType(nullValue)).toBe(false);
|
||||
expect(isMemoType(undefinedValue)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isForwardRefType', () => {
|
||||
it('should return true for an object with $$typeof matching REACT_FORWARD_REF_TYPE', () => {
|
||||
const forwardRefTypeObject = { $$typeof: REACT_FORWARD_REF_TYPE };
|
||||
|
||||
expect(isForwardRefType(forwardRefTypeObject)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for an object with $$typeof not matching REACT_FORWARD_REF_TYPE', () => {
|
||||
const otherTypeObject = { $$typeof: Symbol.for('other.type') };
|
||||
|
||||
expect(isForwardRefType(otherTypeObject)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for an object with no $$typeof property', () => {
|
||||
const noTypeObject = { key: 'value' };
|
||||
|
||||
expect(isForwardRefType(noTypeObject)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for null or undefined', () => {
|
||||
const nullValue = null;
|
||||
const undefinedValue = undefined;
|
||||
|
||||
expect(isForwardRefType(nullValue)).toBe(false);
|
||||
expect(isForwardRefType(undefinedValue)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('acceptsRef', () => {
|
||||
it('should return true for an object with isReactComponent in its prototype', () => {
|
||||
const objWithIsReactComponent = {
|
||||
prototype: {
|
||||
isReactComponent: true,
|
||||
},
|
||||
};
|
||||
|
||||
expect(acceptsRef(objWithIsReactComponent)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true for an object that is forwardRef or memoized forwardRef', () => {
|
||||
const forwardRefObject = React.forwardRef(() => {
|
||||
return null;
|
||||
});
|
||||
|
||||
const memoizedForwardRefObject = React.memo(forwardRefObject);
|
||||
|
||||
expect(acceptsRef(forwardRefObject)).toBe(true);
|
||||
expect(acceptsRef(memoizedForwardRefObject)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for an object without isReactComponent in its prototype', () => {
|
||||
const objWithoutIsReactComponent = {
|
||||
prototype: {
|
||||
someOtherProperty: true,
|
||||
},
|
||||
};
|
||||
|
||||
expect(acceptsRef(objWithoutIsReactComponent)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for null or undefined', () => {
|
||||
const nullValue = null;
|
||||
const undefinedValue = undefined;
|
||||
|
||||
expect(acceptsRef(nullValue)).toBe(false);
|
||||
expect(acceptsRef(undefinedValue)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isReactClass', () => {
|
||||
it('should return true for an object with isReactComponent in its prototype', () => {
|
||||
class ReactClassComponent extends Component {
|
||||
render() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
expect(isReactClass(ReactClassComponent)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true for an object with Component in its prototype chain', () => {
|
||||
class CustomComponent extends Component {
|
||||
render() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
expect(isReactClass(CustomComponent)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for an object without isReactComponent in its prototype', () => {
|
||||
class NonReactComponent {
|
||||
render() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
expect(isReactClass(NonReactComponent)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for null or undefined', () => {
|
||||
const nullValue = null;
|
||||
const undefinedValue = undefined;
|
||||
|
||||
expect(isReactClass(nullValue)).toBe(false);
|
||||
expect(isReactClass(undefinedValue)).toBe(false);
|
||||
});
|
||||
});
|
||||
45
packages/utils/test/src/is-shaken.test.ts
Normal file
45
packages/utils/test/src/is-shaken.test.ts
Normal file
@ -0,0 +1,45 @@
|
||||
import { isShaken } from '../../src/is-shaken';
|
||||
|
||||
describe('isShaken', () => {
|
||||
it('should return true if e1 has shaken property', () => {
|
||||
const e1: any = { shaken: true };
|
||||
const e2: MouseEvent | DragEvent = { target: null } as MouseEvent | DragEvent;
|
||||
|
||||
expect(isShaken(e1, e2)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true if e1.target and e2.target are different', () => {
|
||||
const e1: MouseEvent | DragEvent = { target: {} } as MouseEvent | DragEvent;
|
||||
const e2: MouseEvent | DragEvent = { target: {} } as MouseEvent | DragEvent;
|
||||
|
||||
expect(isShaken(e1, e2)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false if e1 and e2 targets are the same and distance is less than SHAKE_DISTANCE', () => {
|
||||
const target = {};
|
||||
const e1: MouseEvent | DragEvent = { target: target } as MouseEvent | DragEvent;
|
||||
const e2: MouseEvent | DragEvent = { target: target } as MouseEvent | DragEvent;
|
||||
|
||||
// Assuming SHAKE_DISTANCE is 100
|
||||
e1.clientY = 50;
|
||||
e2.clientY = 50;
|
||||
|
||||
e1.clientX = 60;
|
||||
e2.clientX = 60;
|
||||
|
||||
expect(isShaken(e1, e2)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true if e1 and e2 targets are the same and distance is greater than SHAKE_DISTANCE', () => {
|
||||
const e1: MouseEvent | DragEvent = { target: {} } as MouseEvent | DragEvent;
|
||||
const e2: MouseEvent | DragEvent = { target: {} } as MouseEvent | DragEvent;
|
||||
|
||||
// Assuming SHAKE_DISTANCE is 100
|
||||
e1.clientY = 50;
|
||||
e1.clientX = 50;
|
||||
e2.clientY = 200;
|
||||
e2.clientX = 200;
|
||||
|
||||
expect(isShaken(e1, e2)).toBe(true);
|
||||
});
|
||||
});
|
||||
@ -1,4 +1,321 @@
|
||||
import { shouldUseVariableSetter } from '../../src/misc';
|
||||
import {
|
||||
isVariable,
|
||||
isUseI18NSetter,
|
||||
convertToI18NObject,
|
||||
isString,
|
||||
waitForThing,
|
||||
arrShallowEquals,
|
||||
isFromVC,
|
||||
executePendingFn,
|
||||
compatStage,
|
||||
invariant,
|
||||
isRegExp,
|
||||
shouldUseVariableSetter,
|
||||
} from '../../src/misc';
|
||||
import { IPublicModelComponentMeta } from '@alilc/lowcode-types';
|
||||
|
||||
describe('isVariable', () => {
|
||||
it('should return true for a variable object', () => {
|
||||
const variable = { type: 'variable', variable: 'foo', value: 'bar' };
|
||||
const result = isVariable(variable);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for non-variable objects', () => {
|
||||
const obj = { type: 'object' };
|
||||
const result = isVariable(obj);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isUseI18NSetter', () => {
|
||||
it('should return true for a property with I18nSetter', () => {
|
||||
const prototype = { options: { configure: [{ name: 'propName', setter: { type: { displayName: 'I18nSetter' } } }] } };
|
||||
const propName = 'propName';
|
||||
const result = isUseI18NSetter(prototype, propName);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for a property without I18nSetter', () => {
|
||||
const prototype = { options: { configure: [{ name: 'propName', setter: { type: { displayName: 'OtherSetter' } } }] } };
|
||||
const propName = 'propName';
|
||||
const result = isUseI18NSetter(prototype, propName);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('convertToI18NObject', () => {
|
||||
it('should return the input if it is already an I18N object', () => {
|
||||
const i18nObject = { type: 'i18n', use: 'en', en: 'Hello' };
|
||||
const result = convertToI18NObject(i18nObject);
|
||||
expect(result).toEqual(i18nObject);
|
||||
});
|
||||
|
||||
it('should convert a string to an I18N object', () => {
|
||||
const inputString = 'Hello';
|
||||
const result = convertToI18NObject(inputString);
|
||||
const expectedOutput = { type: 'i18n', use: 'zh-CN', 'zh-CN': inputString };
|
||||
expect(result).toEqual(expectedOutput);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isString', () => {
|
||||
it('should return true for a string', () => {
|
||||
const stringValue = 'Hello, world!';
|
||||
const result = isString(stringValue);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true for an empty string', () => {
|
||||
const emptyString = '';
|
||||
const result = isString(emptyString);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for a number', () => {
|
||||
const numberValue = 42; // Not a string
|
||||
const result = isString(numberValue);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for an object', () => {
|
||||
const objectValue = { key: 'value' }; // Not a string
|
||||
const result = isString(objectValue);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for null', () => {
|
||||
const result = isString(null);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for undefined', () => {
|
||||
const undefinedValue = undefined;
|
||||
const result = isString(undefinedValue);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for a boolean', () => {
|
||||
const booleanValue = true; // Not a string
|
||||
const result = isString(booleanValue);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('waitForThing', () => {
|
||||
it('should resolve immediately if the thing is available', async () => {
|
||||
const obj = { prop: 'value' };
|
||||
const path = 'prop';
|
||||
const result = await waitForThing(obj, path);
|
||||
expect(result).toBe('value');
|
||||
});
|
||||
|
||||
it('should resolve after a delay if the thing becomes available', async () => {
|
||||
const obj = { prop: undefined };
|
||||
const path = 'prop';
|
||||
const delay = 100; // Adjust the delay as needed
|
||||
setTimeout(() => {
|
||||
obj.prop = 'value';
|
||||
}, delay);
|
||||
|
||||
const result = await waitForThing(obj, path);
|
||||
expect(result).toBe('value');
|
||||
});
|
||||
});
|
||||
|
||||
describe('arrShallowEquals', () => {
|
||||
it('should return true for two empty arrays', () => {
|
||||
const arr1 = [];
|
||||
const arr2 = [];
|
||||
const result = arrShallowEquals(arr1, arr2);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true for two arrays with the same elements in the same order', () => {
|
||||
const arr1 = [1, 2, 3];
|
||||
const arr2 = [1, 2, 3];
|
||||
const result = arrShallowEquals(arr1, arr2);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true for two arrays with the same elements in a different order', () => {
|
||||
const arr1 = [1, 2, 3];
|
||||
const arr2 = [3, 2, 1];
|
||||
const result = arrShallowEquals(arr1, arr2);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for two arrays with different lengths', () => {
|
||||
const arr1 = [1, 2, 3];
|
||||
const arr2 = [1, 2];
|
||||
const result = arrShallowEquals(arr1, arr2);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for one array and a non-array', () => {
|
||||
const arr1 = [1, 2, 3];
|
||||
const nonArray = 'not an array';
|
||||
const result = arrShallowEquals(arr1, nonArray);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for two arrays with different elements', () => {
|
||||
const arr1 = [1, 2, 3];
|
||||
const arr2 = [3, 4, 5];
|
||||
const result = arrShallowEquals(arr1, arr2);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true for arrays with duplicate elements', () => {
|
||||
const arr1 = [1, 2, 2, 3];
|
||||
const arr2 = [2, 3, 3, 1];
|
||||
const result = arrShallowEquals(arr1, arr2);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isFromVC', () => {
|
||||
it('should return true when advanced configuration is present', () => {
|
||||
// Create a mock meta object with advanced configuration
|
||||
const meta: IPublicModelComponentMeta = {
|
||||
getMetadata: () => ({ configure: { advanced: true } }),
|
||||
};
|
||||
|
||||
const result = isFromVC(meta);
|
||||
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when advanced configuration is not present', () => {
|
||||
// Create a mock meta object without advanced configuration
|
||||
const meta: IPublicModelComponentMeta = {
|
||||
getMetadata: () => ({ configure: { advanced: false } }),
|
||||
};
|
||||
|
||||
const result = isFromVC(meta);
|
||||
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false when meta is undefined', () => {
|
||||
const meta: IPublicModelComponentMeta | undefined = undefined;
|
||||
|
||||
const result = isFromVC(meta);
|
||||
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false when meta does not have configure information', () => {
|
||||
// Create a mock meta object without configure information
|
||||
const meta: IPublicModelComponentMeta = {
|
||||
getMetadata: () => ({}),
|
||||
};
|
||||
|
||||
const result = isFromVC(meta);
|
||||
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false when configure.advanced is not present', () => {
|
||||
// Create a mock meta object with incomplete configure information
|
||||
const meta: IPublicModelComponentMeta = {
|
||||
getMetadata: () => ({ configure: {} }),
|
||||
};
|
||||
|
||||
const result = isFromVC(meta);
|
||||
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('executePendingFn', () => {
|
||||
it('should execute the provided function after the specified timeout', async () => {
|
||||
// Mock the function to execute
|
||||
const fn = jest.fn();
|
||||
|
||||
// Call executePendingFn with the mocked function and a short timeout
|
||||
executePendingFn(fn, 100);
|
||||
|
||||
// Ensure the function has not been called immediately
|
||||
expect(fn).not.toHaveBeenCalled();
|
||||
|
||||
// Wait for the specified timeout
|
||||
await new Promise(resolve => setTimeout(resolve, 100));
|
||||
|
||||
// Ensure the function has been called after the timeout
|
||||
expect(fn).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should execute the provided function with a default timeout if not specified', async () => {
|
||||
// Mock the function to execute
|
||||
const fn = jest.fn();
|
||||
|
||||
// Call executePendingFn with the mocked function without specifying a timeout
|
||||
executePendingFn(fn);
|
||||
|
||||
// Ensure the function has not been called immediately
|
||||
expect(fn).not.toHaveBeenCalled();
|
||||
|
||||
// Wait for the default timeout (2000 milliseconds)
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
// Ensure the function has been called after the default timeout
|
||||
expect(fn).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('compatStage', () => {
|
||||
it('should convert a number to an enum stage', () => {
|
||||
const result = compatStage(3);
|
||||
expect(result).toBe('save');
|
||||
});
|
||||
|
||||
it('should warn about the deprecated usage', () => {
|
||||
const warnSpy = jest.spyOn(console, 'warn');
|
||||
const result = compatStage(2);
|
||||
expect(result).toBe('serilize');
|
||||
expect(warnSpy).toHaveBeenCalledWith(
|
||||
'stage 直接指定为数字的使用方式已经过时,将在下一版本移除,请直接使用 IPublicEnumTransformStage.Render|Serilize|Save|Clone|Init|Upgrade'
|
||||
);
|
||||
warnSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('should return the enum stage if it is already an enum', () => {
|
||||
const result = compatStage('render');
|
||||
expect(result).toBe('render');
|
||||
});
|
||||
});
|
||||
|
||||
describe('invariant', () => {
|
||||
it('should not throw an error if the check is true', () => {
|
||||
expect(() => invariant(true, 'Test invariant', 'thing')).not.toThrow();
|
||||
});
|
||||
|
||||
it('should throw an error if the check is false', () => {
|
||||
expect(() => invariant(false, 'Test invariant', 'thing')).toThrowError(
|
||||
"Invariant failed: Test invariant in 'thing'"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isRegExp', () => {
|
||||
it('should return true for a valid RegExp', () => {
|
||||
const regex = /test/;
|
||||
const result = isRegExp(regex);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for a non-RegExp object', () => {
|
||||
const nonRegExp = { test: /test/ };
|
||||
const result = isRegExp(nonRegExp);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for null', () => {
|
||||
const result = isRegExp(null);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
it('shouldUseVariableSetter', () => {
|
||||
expect(shouldUseVariableSetter(false, true)).toBeFalsy();
|
||||
|
||||
18
packages/utils/test/src/navtive-selection.test.ts
Normal file
18
packages/utils/test/src/navtive-selection.test.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { setNativeSelection, nativeSelectionEnabled } from '../../src/navtive-selection';
|
||||
|
||||
describe('setNativeSelection', () => {
|
||||
beforeEach(() => {
|
||||
// 在每个测试运行之前重置nativeSelectionEnabled的值
|
||||
setNativeSelection(true);
|
||||
});
|
||||
|
||||
test('should enable native selection', () => {
|
||||
setNativeSelection(true);
|
||||
expect(nativeSelectionEnabled).toBe(true);
|
||||
});
|
||||
|
||||
test('should disable native selection', () => {
|
||||
setNativeSelection(false);
|
||||
expect(nativeSelectionEnabled).toBe(false);
|
||||
});
|
||||
});
|
||||
@ -1,4 +1,132 @@
|
||||
import { compatibleLegaoSchema } from '../../src/schema';
|
||||
import {
|
||||
compatibleLegaoSchema,
|
||||
getNodeSchemaById,
|
||||
applyActivities,
|
||||
} from '../../src/schema';
|
||||
import { ActivityType } from '@alilc/lowcode-types';
|
||||
|
||||
describe('compatibleLegaoSchema', () => {
|
||||
it('should handle null input', () => {
|
||||
const result = compatibleLegaoSchema(null);
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it('should convert Legao schema to JSExpression', () => {
|
||||
// Create your test input
|
||||
const legaoSchema = {
|
||||
type: 'LegaoType',
|
||||
source: 'LegaoSource',
|
||||
compiled: 'LegaoCompiled',
|
||||
};
|
||||
const result = compatibleLegaoSchema(legaoSchema);
|
||||
|
||||
// Define the expected output
|
||||
const expectedOutput = {
|
||||
type: 'JSExpression',
|
||||
value: 'LegaoCompiled',
|
||||
extType: 'function',
|
||||
};
|
||||
|
||||
// Assert that the result matches the expected output
|
||||
expect(result).toEqual(expectedOutput);
|
||||
});
|
||||
|
||||
// Add more test cases for other scenarios
|
||||
});
|
||||
|
||||
describe('getNodeSchemaById', () => {
|
||||
it('should find a node in the schema', () => {
|
||||
// Create your test schema and node ID
|
||||
const testSchema = {
|
||||
id: 'root',
|
||||
children: [
|
||||
{
|
||||
id: 'child1',
|
||||
children: [
|
||||
{
|
||||
id: 'child1.1',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
const nodeId = 'child1.1';
|
||||
|
||||
const result = getNodeSchemaById(testSchema, nodeId);
|
||||
|
||||
// Define the expected output
|
||||
const expectedOutput = {
|
||||
id: 'child1.1',
|
||||
};
|
||||
|
||||
// Assert that the result matches the expected output
|
||||
expect(result).toEqual(expectedOutput);
|
||||
});
|
||||
|
||||
// Add more test cases for other scenarios
|
||||
});
|
||||
|
||||
describe('applyActivities', () => {
|
||||
it('should apply ADD activity', () => {
|
||||
// Create your test schema and activities
|
||||
const testSchema = {
|
||||
id: 'root',
|
||||
children: [
|
||||
{
|
||||
id: 'child1',
|
||||
children: [
|
||||
{
|
||||
id: 'child1.1',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
const activities = [
|
||||
{
|
||||
type: ActivityType.ADDED,
|
||||
payload: {
|
||||
location: {
|
||||
parent: {
|
||||
nodeId: 'child1',
|
||||
index: 0,
|
||||
},
|
||||
},
|
||||
schema: {
|
||||
id: 'newChild',
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const result = applyActivities(testSchema, activities);
|
||||
|
||||
// Define the expected output
|
||||
const expectedOutput = {
|
||||
id: 'root',
|
||||
children: [
|
||||
{
|
||||
id: 'child1',
|
||||
children: [
|
||||
{
|
||||
id: 'newChild',
|
||||
},
|
||||
{
|
||||
id: 'child1.1',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
// Assert that the result matches the expected output
|
||||
expect(result).toEqual(expectedOutput);
|
||||
});
|
||||
|
||||
// Add more test cases for other activity types and scenarios
|
||||
});
|
||||
|
||||
|
||||
describe('Schema Ut', () => {
|
||||
it('props', () => {
|
||||
const schema = {
|
||||
|
||||
47
packages/utils/test/src/script.test.ts
Normal file
47
packages/utils/test/src/script.test.ts
Normal file
@ -0,0 +1,47 @@
|
||||
import {
|
||||
evaluate,
|
||||
evaluateExpression,
|
||||
newFunction,
|
||||
} from '../../src/script';
|
||||
|
||||
describe('evaluate', () => {
|
||||
test('should evaluate the given script', () => {
|
||||
const script = 'console.log("Hello, world!");';
|
||||
global.console = { log: jest.fn() };
|
||||
|
||||
evaluate(script);
|
||||
|
||||
expect(global.console.log).toHaveBeenCalledWith('Hello, world!');
|
||||
});
|
||||
});
|
||||
|
||||
describe('evaluateExpression', () => {
|
||||
test('should evaluate the given expression', () => {
|
||||
const expr = 'return 1 + 2';
|
||||
|
||||
const result = evaluateExpression(expr);
|
||||
|
||||
expect(result).toBe(3);
|
||||
});
|
||||
});
|
||||
|
||||
describe('newFunction', () => {
|
||||
test('should create a new function with the given arguments and code', () => {
|
||||
const args = 'a, b';
|
||||
const code = 'return a + b';
|
||||
|
||||
const result = newFunction(args, code);
|
||||
|
||||
expect(result).toBeInstanceOf(Function);
|
||||
expect(result(1, 2)).toBe(3);
|
||||
});
|
||||
|
||||
test('should return null if an error occurs', () => {
|
||||
const args = 'a, b';
|
||||
const code = 'return a +;'; // Invalid code
|
||||
|
||||
const result = newFunction(args, code);
|
||||
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
});
|
||||
35
packages/utils/test/src/svg-icon.test.tsx
Normal file
35
packages/utils/test/src/svg-icon.test.tsx
Normal file
@ -0,0 +1,35 @@
|
||||
import React from 'react';
|
||||
import { render } from '@testing-library/react';
|
||||
import { SVGIcon, IconProps } from '../../src/svg-icon';
|
||||
|
||||
describe('SVGIcon', () => {
|
||||
it('should render SVG element with correct size', () => {
|
||||
const iconProps: IconProps = {
|
||||
size: 'small',
|
||||
viewBox: '0 0 24 24',
|
||||
};
|
||||
|
||||
const { container } = render(<SVGIcon {...iconProps} />);
|
||||
|
||||
const svgElement = container.querySelector('svg');
|
||||
|
||||
expect(svgElement).toHaveAttribute('width', '12');
|
||||
expect(svgElement).toHaveAttribute('height', '12');
|
||||
});
|
||||
|
||||
it('should render SVG element with custom size', () => {
|
||||
const iconProps: IconProps = {
|
||||
size: 24,
|
||||
viewBox: '0 0 24 24',
|
||||
};
|
||||
|
||||
const { container } = render(<SVGIcon {...iconProps} />);
|
||||
|
||||
const svgElement = container.querySelector('svg');
|
||||
|
||||
expect(svgElement).toHaveAttribute('width', '24');
|
||||
expect(svgElement).toHaveAttribute('height', '24');
|
||||
});
|
||||
|
||||
// Add more tests for other scenarios if needed
|
||||
});
|
||||
58
packages/utils/test/src/transaction-manager.test.ts
Normal file
58
packages/utils/test/src/transaction-manager.test.ts
Normal file
@ -0,0 +1,58 @@
|
||||
import { transactionManager } from '../../src/transaction-manager';
|
||||
import { IPublicEnumTransitionType } from '@alilc/lowcode-types';
|
||||
|
||||
const type = IPublicEnumTransitionType.REPAINT;
|
||||
|
||||
describe('TransactionManager', () => {
|
||||
let fn1: jest.Mock;
|
||||
let fn2: jest.Mock;
|
||||
|
||||
beforeEach(() => {
|
||||
fn1 = jest.fn();
|
||||
fn2 = jest.fn();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
test('executeTransaction should emit startTransaction and endTransaction events', () => {
|
||||
const startTransactionSpy = jest.spyOn(transactionManager.emitter, 'emit');
|
||||
const endTransactionSpy = jest.spyOn(transactionManager.emitter, 'emit');
|
||||
|
||||
transactionManager.executeTransaction(() => {
|
||||
// Perform some action within the transaction
|
||||
});
|
||||
|
||||
expect(startTransactionSpy).toHaveBeenCalledWith(`[${type}]startTransaction`);
|
||||
expect(endTransactionSpy).toHaveBeenCalledWith(`[${type}]endTransaction`);
|
||||
});
|
||||
|
||||
test('onStartTransaction should register the provided function for startTransaction event', () => {
|
||||
const offSpy = jest.spyOn(transactionManager.emitter, 'off');
|
||||
|
||||
const offFunction = transactionManager.onStartTransaction(fn1);
|
||||
|
||||
expect(transactionManager.emitter.listenerCount(`[${type}]startTransaction`)).toBe(1);
|
||||
expect(offSpy).not.toHaveBeenCalled();
|
||||
|
||||
offFunction();
|
||||
|
||||
expect(transactionManager.emitter.listenerCount(`[${type}]startTransaction`)).toBe(0);
|
||||
expect(offSpy).toHaveBeenCalledWith(`[${type}]startTransaction`, fn1);
|
||||
});
|
||||
|
||||
test('onEndTransaction should register the provided function for endTransaction event', () => {
|
||||
const offSpy = jest.spyOn(transactionManager.emitter, 'off');
|
||||
|
||||
const offFunction = transactionManager.onEndTransaction(fn2);
|
||||
|
||||
expect(transactionManager.emitter.listenerCount(`[${type}]endTransaction`)).toBe(1);
|
||||
expect(offSpy).not.toHaveBeenCalled();
|
||||
|
||||
offFunction();
|
||||
|
||||
expect(transactionManager.emitter.listenerCount(`[${type}]endTransaction`)).toBe(0);
|
||||
expect(offSpy).toHaveBeenCalledWith(`[${type}]endTransaction`, fn2);
|
||||
});
|
||||
});
|
||||
11
packages/utils/test/src/unique-id.test.ts
Normal file
11
packages/utils/test/src/unique-id.test.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { uniqueId } from '../../src/unique-id';
|
||||
|
||||
test('uniqueId should return a unique id with prefix', () => {
|
||||
const id = uniqueId('test');
|
||||
expect(id.startsWith('test')).toBeTruthy();
|
||||
});
|
||||
|
||||
test('uniqueId should return a unique id without prefix', () => {
|
||||
const id = uniqueId();
|
||||
expect(id).not.toBeFalsy();
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user