mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-01-26 03:48:12 +00:00
Merge branch 'develop' into release/1.0.80
This commit is contained in:
commit
f6538b6704
@ -342,9 +342,11 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
|
|||||||
const _library = library || (this.get('library') as LibraryItem[]);
|
const _library = library || (this.get('library') as LibraryItem[]);
|
||||||
const libraryAsset: AssetList = [];
|
const libraryAsset: AssetList = [];
|
||||||
const libraryExportList: string[] = [];
|
const libraryExportList: string[] = [];
|
||||||
|
const functionCallLibraryExportList: string[] = [];
|
||||||
|
|
||||||
if (_library && _library.length) {
|
if (_library && _library.length) {
|
||||||
_library.forEach((item) => {
|
_library.forEach((item) => {
|
||||||
|
const { exportMode, exportSourceLibrary } = item;
|
||||||
this.libraryMap[item.package] = item.library;
|
this.libraryMap[item.package] = item.library;
|
||||||
if (item.async) {
|
if (item.async) {
|
||||||
this.asyncLibraryMap[item.package] = item;
|
this.asyncLibraryMap[item.package] = item;
|
||||||
@ -354,6 +356,11 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
|
|||||||
`Object.defineProperty(window,'${item.exportName}',{get:()=>window.${item.library}});`,
|
`Object.defineProperty(window,'${item.exportName}',{get:()=>window.${item.library}});`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (exportMode === 'functionCall' && exportSourceLibrary) {
|
||||||
|
functionCallLibraryExportList.push(
|
||||||
|
`window["${item.library}"] = window["${exportSourceLibrary}"]("${item.library}", "${item.package}");`,
|
||||||
|
);
|
||||||
|
}
|
||||||
if (item.editUrls) {
|
if (item.editUrls) {
|
||||||
libraryAsset.push(item.editUrls);
|
libraryAsset.push(item.editUrls);
|
||||||
} else if (item.urls) {
|
} else if (item.urls) {
|
||||||
@ -362,7 +369,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
libraryAsset.unshift(assetItem(AssetType.JSText, libraryExportList.join('')));
|
libraryAsset.unshift(assetItem(AssetType.JSText, libraryExportList.join('')));
|
||||||
|
libraryAsset.push(assetItem(AssetType.JSText, functionCallLibraryExportList.join('')));
|
||||||
return libraryAsset;
|
return libraryAsset;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -418,6 +425,9 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
|
|||||||
if (Object.keys(this.asyncLibraryMap).length > 0) {
|
if (Object.keys(this.asyncLibraryMap).length > 0) {
|
||||||
// 加载异步Library
|
// 加载异步Library
|
||||||
await renderer.loadAsyncLibrary(this.asyncLibraryMap);
|
await renderer.loadAsyncLibrary(this.asyncLibraryMap);
|
||||||
|
Object.keys(this.asyncLibraryMap).forEach(key => {
|
||||||
|
delete this.asyncLibraryMap[key];
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// step 5 ready & render
|
// step 5 ready & render
|
||||||
@ -437,7 +447,14 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
|
|||||||
|
|
||||||
async setupComponents(library) {
|
async setupComponents(library) {
|
||||||
const libraryAsset: AssetList = this.buildLibrary(library);
|
const libraryAsset: AssetList = this.buildLibrary(library);
|
||||||
await this.renderer.load(libraryAsset);
|
await this.renderer?.load(libraryAsset);
|
||||||
|
if (Object.keys(this.asyncLibraryMap).length > 0) {
|
||||||
|
// 加载异步Library
|
||||||
|
await this.renderer?.loadAsyncLibrary(this.asyncLibraryMap);
|
||||||
|
Object.keys(this.asyncLibraryMap).forEach(key => {
|
||||||
|
delete this.asyncLibraryMap[key];
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setupEvents() {
|
setupEvents() {
|
||||||
|
|||||||
@ -11,6 +11,7 @@ export interface BuiltinSimulatorRenderer {
|
|||||||
setNativeSelection(enableFlag: boolean): void;
|
setNativeSelection(enableFlag: boolean): void;
|
||||||
setDraggingState(state: boolean): void;
|
setDraggingState(state: boolean): void;
|
||||||
setCopyState(state: boolean): void;
|
setCopyState(state: boolean): void;
|
||||||
|
loadAsyncLibrary(asyncMap: { [index: string]: any }): void;
|
||||||
clearState(): void;
|
clearState(): void;
|
||||||
run(): void;
|
run(): void;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -199,6 +199,8 @@ exports[`React Renderer render basic case 1`] = `
|
|||||||
maxLength={null}
|
maxLength={null}
|
||||||
onBlur={[Function]}
|
onBlur={[Function]}
|
||||||
onChange={[Function]}
|
onChange={[Function]}
|
||||||
|
onCompositionEnd={[Function]}
|
||||||
|
onCompositionStart={[Function]}
|
||||||
onFocus={[Function]}
|
onFocus={[Function]}
|
||||||
onKeyDown={[Function]}
|
onKeyDown={[Function]}
|
||||||
placeholder="请选择"
|
placeholder="请选择"
|
||||||
@ -296,6 +298,8 @@ exports[`React Renderer render basic case 1`] = `
|
|||||||
maxLength={null}
|
maxLength={null}
|
||||||
onBlur={[Function]}
|
onBlur={[Function]}
|
||||||
onChange={[Function]}
|
onChange={[Function]}
|
||||||
|
onCompositionEnd={[Function]}
|
||||||
|
onCompositionStart={[Function]}
|
||||||
onFocus={[Function]}
|
onFocus={[Function]}
|
||||||
onKeyDown={[Function]}
|
onKeyDown={[Function]}
|
||||||
placeholder="请选择"
|
placeholder="请选择"
|
||||||
@ -378,6 +382,8 @@ exports[`React Renderer render basic case 1`] = `
|
|||||||
maxLength={null}
|
maxLength={null}
|
||||||
onBlur={[Function]}
|
onBlur={[Function]}
|
||||||
onChange={[Function]}
|
onChange={[Function]}
|
||||||
|
onCompositionEnd={[Function]}
|
||||||
|
onCompositionStart={[Function]}
|
||||||
onFocus={[Function]}
|
onFocus={[Function]}
|
||||||
onKeyDown={[Function]}
|
onKeyDown={[Function]}
|
||||||
readOnly={false}
|
readOnly={false}
|
||||||
@ -826,6 +832,8 @@ exports[`React Renderer render basic case 1`] = `
|
|||||||
maxLength={null}
|
maxLength={null}
|
||||||
onBlur={[Function]}
|
onBlur={[Function]}
|
||||||
onChange={[Function]}
|
onChange={[Function]}
|
||||||
|
onCompositionEnd={[Function]}
|
||||||
|
onCompositionStart={[Function]}
|
||||||
onFocus={[Function]}
|
onFocus={[Function]}
|
||||||
onKeyDown={[Function]}
|
onKeyDown={[Function]}
|
||||||
readOnly={false}
|
readOnly={false}
|
||||||
|
|||||||
6
packages/renderer-core/build.test.json
Normal file
6
packages/renderer-core/build.test.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"plugins": [
|
||||||
|
"build-plugin-component",
|
||||||
|
"@ali/lowcode-test-mate/plugin/index.ts"
|
||||||
|
]
|
||||||
|
}
|
||||||
20
packages/renderer-core/jest.config.js
Normal file
20
packages/renderer-core/jest.config.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
const esModules = ['@recore/obx-react'].join('|');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
// transform: {
|
||||||
|
// '^.+\\.[jt]sx?$': 'babel-jest',
|
||||||
|
// // '^.+\\.(ts|tsx)$': 'ts-jest',
|
||||||
|
// // '^.+\\.(js|jsx)$': 'babel-jest',
|
||||||
|
// },
|
||||||
|
// testMatch: ['(/tests?/.*(test))\\.[jt]s$'],
|
||||||
|
transformIgnorePatterns: [
|
||||||
|
`/node_modules/(?!${esModules})/`,
|
||||||
|
],
|
||||||
|
moduleFileExtensions: ['ts', 'tsx', 'js', 'json'],
|
||||||
|
collectCoverage: true,
|
||||||
|
collectCoverageFrom: [
|
||||||
|
'src/**/*.{ts,tsx}',
|
||||||
|
'!**/node_modules/**',
|
||||||
|
'!**/vendor/**',
|
||||||
|
],
|
||||||
|
};
|
||||||
@ -10,8 +10,13 @@
|
|||||||
"es"
|
"es"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"test": "build-scripts test --config build.test.json",
|
||||||
"build": "build-scripts build --skip-demo"
|
"build": "build-scripts build --skip-demo"
|
||||||
},
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git@gitlab.alibaba-inc.com:ali-lowcode/ali-lowcode-engine.git"
|
||||||
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ali/b3-one": "^0.0.17",
|
"@ali/b3-one": "^0.0.17",
|
||||||
"@ali/bzb-request": "^2.6.0-beta.13",
|
"@ali/bzb-request": "^2.6.0-beta.13",
|
||||||
|
|||||||
@ -32,7 +32,7 @@ import { compWrapper } from '../hoc';
|
|||||||
import { IComponentConstruct, IComponentHoc, leafWrapper } from '../hoc/leaf';
|
import { IComponentConstruct, IComponentHoc, leafWrapper } from '../hoc/leaf';
|
||||||
import logger from '../utils/logger';
|
import logger from '../utils/logger';
|
||||||
|
|
||||||
export default function baseRenererFactory() {
|
export default function baseRendererFactory() {
|
||||||
const { BaseRenderer: customBaseRenderer } = adapter.getRenderers();
|
const { BaseRenderer: customBaseRenderer } = adapter.getRenderers();
|
||||||
|
|
||||||
if (customBaseRenderer) {
|
if (customBaseRenderer) {
|
||||||
@ -712,7 +712,7 @@ export default function baseRenererFactory() {
|
|||||||
) {
|
) {
|
||||||
return checkProps(props);
|
return checkProps(props);
|
||||||
}
|
}
|
||||||
if (isJSExpression(props)) {
|
if (isJSExpression(props) || isJSFunction(props)) {
|
||||||
props = parseExpression(props, scope);
|
props = parseExpression(props, scope);
|
||||||
// 只有当变量解析出来为模型结构的时候才会继续解析
|
// 只有当变量解析出来为模型结构的时候才会继续解析
|
||||||
if (!isSchema(props) && !isJSSlot(props)) return checkProps(props);
|
if (!isSchema(props) && !isJSSlot(props)) return checkProps(props);
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
import { BuiltinSimulatorHost } from '@ali/lowcode-designer';
|
import { BuiltinSimulatorHost } from '@ali/lowcode-designer';
|
||||||
import { baseRendererFactory } from '../renderer';
|
import { baseRendererFactory } from '../renderer';
|
||||||
import baseRenererFactory from '../renderer/base';
|
|
||||||
|
|
||||||
export type IBaseRenderer = ReturnType<typeof baseRenererFactory>;
|
export type IBaseRenderer = ReturnType<typeof baseRendererFactory>;
|
||||||
export type IBaseRendererInstance = InstanceType<ReturnType<typeof baseRendererFactory>>;
|
export type IBaseRendererInstance = InstanceType<ReturnType<typeof baseRendererFactory>>;
|
||||||
|
|
||||||
export interface IProps {
|
export interface IProps {
|
||||||
@ -28,7 +27,7 @@ export interface IProps {
|
|||||||
|
|
||||||
export interface IState {
|
export interface IState {
|
||||||
engineRenderError?: boolean;
|
engineRenderError?: boolean;
|
||||||
error?: Error
|
error?: Error;
|
||||||
onCompGetRef: (schema: ISchema, ref: any) => void;
|
onCompGetRef: (schema: ISchema, ref: any) => void;
|
||||||
onCompGetCtx: (schema: ISchema, ref: any) => void;
|
onCompGetCtx: (schema: ISchema, ref: any) => void;
|
||||||
customCreateElement: (...args: any) => any;
|
customCreateElement: (...args: any) => any;
|
||||||
@ -57,7 +56,7 @@ export interface ComponentModel {
|
|||||||
export interface ISchema {
|
export interface ISchema {
|
||||||
componentName: string;
|
componentName: string;
|
||||||
props: any;
|
props: any;
|
||||||
children: ComponentModel[]
|
children: ComponentModel[];
|
||||||
dataSource?: any;
|
dataSource?: any;
|
||||||
methods?: any;
|
methods?: any;
|
||||||
lifeCycles?: any;
|
lifeCycles?: any;
|
||||||
@ -68,7 +67,7 @@ export interface IInfo {
|
|||||||
schema: ISchema;
|
schema: ISchema;
|
||||||
Comp: any;
|
Comp: any;
|
||||||
componentInfo?: any;
|
componentInfo?: any;
|
||||||
componentChildren?: any
|
componentChildren?: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface JSExpression {
|
export interface JSExpression {
|
||||||
@ -113,9 +112,9 @@ export interface IRendererModules {
|
|||||||
BaseRenderer?: new(...args: any) => IRenderer;
|
BaseRenderer?: new(...args: any) => IRenderer;
|
||||||
PageRenderer: any;
|
PageRenderer: any;
|
||||||
ComponentRenderer: any;
|
ComponentRenderer: any;
|
||||||
BlockRenderer?: any,
|
BlockRenderer?: any;
|
||||||
AddonRenderer?: any,
|
AddonRenderer?: any;
|
||||||
TempRenderer?: any,
|
TempRenderer?: any;
|
||||||
DivRenderer?: any;
|
DivRenderer?: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
567
packages/renderer-core/test/fixtures/schema/basic.ts
vendored
Normal file
567
packages/renderer-core/test/fixtures/schema/basic.ts
vendored
Normal file
@ -0,0 +1,567 @@
|
|||||||
|
export default {
|
||||||
|
componentName: 'Page',
|
||||||
|
id: 'node_dockcviv8fo1',
|
||||||
|
props: {
|
||||||
|
ref: 'outterView',
|
||||||
|
autoLoading: true,
|
||||||
|
style: {
|
||||||
|
padding: '0 5px 0 5px',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
fileName: 'test',
|
||||||
|
dataSource: {
|
||||||
|
list: [],
|
||||||
|
},
|
||||||
|
state: {
|
||||||
|
text: 'outter',
|
||||||
|
isShowDialog: false,
|
||||||
|
},
|
||||||
|
css: 'body {font-size: 12px;} .botton{width:100px;color:#ff00ff}',
|
||||||
|
lifeCycles: {
|
||||||
|
componentDidMount: {
|
||||||
|
type: 'JSFunction',
|
||||||
|
value: "function() {\n console.log('did mount');\n }",
|
||||||
|
},
|
||||||
|
componentWillUnmount: {
|
||||||
|
type: 'JSFunction',
|
||||||
|
value: "function() {\n console.log('will umount');\n }",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
testFunc: {
|
||||||
|
type: 'JSFunction',
|
||||||
|
value: "function() {\n console.log('test func');\n }",
|
||||||
|
},
|
||||||
|
onClick: {
|
||||||
|
type: 'JSFunction',
|
||||||
|
value: 'function() {\n this.setState({\n isShowDialog: true\n })\n }',
|
||||||
|
},
|
||||||
|
closeDialog: {
|
||||||
|
type: 'JSFunction',
|
||||||
|
value: 'function() {\n this.setState({\n isShowDialog: false\n })\n }',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: 'Box',
|
||||||
|
id: 'node_dockcy8n9xed',
|
||||||
|
props: {
|
||||||
|
style: {
|
||||||
|
backgroundColor: 'rgba(31,56,88,0.1)',
|
||||||
|
padding: '12px 12px 12px 12px',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: 'Box',
|
||||||
|
id: 'node_dockcy8n9xee',
|
||||||
|
props: {
|
||||||
|
style: {
|
||||||
|
padding: '12px 12px 12px 12px',
|
||||||
|
backgroundColor: '#ffffff',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: 'Breadcrumb',
|
||||||
|
id: 'node_dockcy8n9xef',
|
||||||
|
props: {
|
||||||
|
prefix: 'next-',
|
||||||
|
maxNode: 100,
|
||||||
|
component: 'nav',
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: 'Breadcrumb.Item',
|
||||||
|
id: 'node_dockcy8n9xeg',
|
||||||
|
props: {
|
||||||
|
prefix: 'next-',
|
||||||
|
children: '首页',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'Breadcrumb.Item',
|
||||||
|
id: 'node_dockcy8n9xei',
|
||||||
|
props: {
|
||||||
|
prefix: 'next-',
|
||||||
|
children: '品质中台',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'Breadcrumb.Item',
|
||||||
|
id: 'node_dockcy8n9xek',
|
||||||
|
props: {
|
||||||
|
prefix: 'next-',
|
||||||
|
children: '商家品质页面管理',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'Breadcrumb.Item',
|
||||||
|
id: 'node_dockcy8n9xem',
|
||||||
|
props: {
|
||||||
|
prefix: 'next-',
|
||||||
|
children: '质检知识条配置',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'Box',
|
||||||
|
id: 'node_dockcy8n9xeo',
|
||||||
|
props: {
|
||||||
|
style: {
|
||||||
|
marginTop: '12px',
|
||||||
|
backgroundColor: '#ffffff',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: 'Form',
|
||||||
|
id: 'node_dockcy8n9xep',
|
||||||
|
props: {
|
||||||
|
inline: true,
|
||||||
|
style: {
|
||||||
|
marginTop: '12px',
|
||||||
|
marginRight: '12px',
|
||||||
|
marginLeft: '12px',
|
||||||
|
},
|
||||||
|
__events: [],
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: 'Form.Item',
|
||||||
|
id: 'node_dockcy8n9xeq',
|
||||||
|
props: {
|
||||||
|
style: {
|
||||||
|
marginBottom: '0',
|
||||||
|
},
|
||||||
|
label: '类目名:',
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: 'Select',
|
||||||
|
id: 'node_dockcy8n9xer',
|
||||||
|
props: {
|
||||||
|
mode: 'single',
|
||||||
|
hasArrow: true,
|
||||||
|
cacheValue: true,
|
||||||
|
style: {
|
||||||
|
width: '150px',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'Form.Item',
|
||||||
|
id: 'node_dockcy8n9xes',
|
||||||
|
props: {
|
||||||
|
style: {
|
||||||
|
marginBottom: '0',
|
||||||
|
},
|
||||||
|
label: '项目类型:',
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: 'Select',
|
||||||
|
id: 'node_dockcy8n9xet',
|
||||||
|
props: {
|
||||||
|
mode: 'single',
|
||||||
|
hasArrow: true,
|
||||||
|
cacheValue: true,
|
||||||
|
style: {
|
||||||
|
width: '200px',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'Form.Item',
|
||||||
|
id: 'node_dockcy8n9xeu',
|
||||||
|
props: {
|
||||||
|
style: {
|
||||||
|
marginBottom: '0',
|
||||||
|
},
|
||||||
|
label: '项目 ID:',
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: 'Input',
|
||||||
|
id: 'node_dockcy8n9xev',
|
||||||
|
props: {
|
||||||
|
hasBorder: true,
|
||||||
|
size: 'medium',
|
||||||
|
autoComplete: 'off',
|
||||||
|
style: {
|
||||||
|
width: '200px',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'Button.Group',
|
||||||
|
id: 'node_dockcy8n9xew',
|
||||||
|
props: {},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: 'Button',
|
||||||
|
id: 'node_dockcy8n9xex',
|
||||||
|
props: {
|
||||||
|
type: 'primary',
|
||||||
|
style: {
|
||||||
|
margin: '0 5px 0 5px',
|
||||||
|
},
|
||||||
|
htmlType: 'submit',
|
||||||
|
children: '搜索',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'Button',
|
||||||
|
id: 'node_dockcy8n9xe10',
|
||||||
|
props: {
|
||||||
|
type: 'normal',
|
||||||
|
style: {
|
||||||
|
margin: '0 5px 0 5px',
|
||||||
|
},
|
||||||
|
htmlType: 'reset',
|
||||||
|
children: '清空',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'Box',
|
||||||
|
id: 'node_dockcy8n9xe1f',
|
||||||
|
props: {
|
||||||
|
style: {
|
||||||
|
backgroundColor: '#ffffff',
|
||||||
|
paddingBottom: '24px',
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'flex-end',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: 'Button',
|
||||||
|
id: 'node_dockd5nrh9p4',
|
||||||
|
props: {
|
||||||
|
type: 'primary',
|
||||||
|
size: 'medium',
|
||||||
|
htmlType: 'button',
|
||||||
|
component: 'button',
|
||||||
|
children: '新建配置',
|
||||||
|
style: {},
|
||||||
|
__events: [
|
||||||
|
{
|
||||||
|
type: 'componentEvent',
|
||||||
|
name: 'onClick',
|
||||||
|
relatedEventName: 'onClick',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
onClick: {
|
||||||
|
type: 'JSFunction',
|
||||||
|
value: 'function(){ this.onClick() }',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'Box',
|
||||||
|
id: 'node_dockd5nrh9p5',
|
||||||
|
props: {},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: 'Table',
|
||||||
|
id: 'node_dockjielosj1',
|
||||||
|
props: {
|
||||||
|
showMiniPager: true,
|
||||||
|
showActionBar: true,
|
||||||
|
actionBar: [
|
||||||
|
{
|
||||||
|
title: '新增',
|
||||||
|
type: 'primary',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '编辑',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
dataKey: 'name',
|
||||||
|
width: 200,
|
||||||
|
align: 'center',
|
||||||
|
title: '姓名',
|
||||||
|
editType: 'text',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataKey: 'age',
|
||||||
|
width: 200,
|
||||||
|
align: 'center',
|
||||||
|
title: '年龄',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataKey: 'email',
|
||||||
|
width: 200,
|
||||||
|
align: 'center',
|
||||||
|
title: '邮箱',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
name: '王小',
|
||||||
|
id: '1',
|
||||||
|
age: 15000,
|
||||||
|
email: 'aaa@abc.com',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '王中',
|
||||||
|
id: '2',
|
||||||
|
age: 25000,
|
||||||
|
email: 'bbb@abc.com',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '王大',
|
||||||
|
id: '3',
|
||||||
|
age: 35000,
|
||||||
|
email: 'ccc@abc.com',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
actionTitle: '操作',
|
||||||
|
actionWidth: 180,
|
||||||
|
actionType: 'link',
|
||||||
|
actionFixed: 'right',
|
||||||
|
actionHidden: false,
|
||||||
|
maxWebShownActionCount: 2,
|
||||||
|
actionColumn: [
|
||||||
|
{
|
||||||
|
title: '编辑',
|
||||||
|
callback: {
|
||||||
|
type: 'JSFunction',
|
||||||
|
value: '(rowData, action, table) => {\n return table.editRow(rowData).then((row) => {\n console.log(row);\n });\n }',
|
||||||
|
},
|
||||||
|
device: [
|
||||||
|
'desktop',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '保存',
|
||||||
|
callback: {
|
||||||
|
type: 'JSFunction',
|
||||||
|
value: '(rowData, action, table) => { \nreturn table.saveRow(rowData).then((row) => { \nconsole.log(row); \n}); \n}',
|
||||||
|
},
|
||||||
|
mode: 'EDIT',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'Box',
|
||||||
|
id: 'node_dockd5nrh9pg',
|
||||||
|
props: {
|
||||||
|
style: {
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'flex-end',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: 'Pagination',
|
||||||
|
id: 'node_dockd5nrh9pf',
|
||||||
|
props: {
|
||||||
|
prefix: 'next-',
|
||||||
|
type: 'normal',
|
||||||
|
shape: 'normal',
|
||||||
|
size: 'medium',
|
||||||
|
defaultCurrent: 1,
|
||||||
|
total: 100,
|
||||||
|
pageShowCount: 5,
|
||||||
|
pageSize: 10,
|
||||||
|
pageSizePosition: 'start',
|
||||||
|
showJump: true,
|
||||||
|
style: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'Dialog',
|
||||||
|
id: 'node_dockcy8n9xe1h',
|
||||||
|
props: {
|
||||||
|
prefix: 'next-',
|
||||||
|
footerAlign: 'right',
|
||||||
|
footerActions: [
|
||||||
|
'ok',
|
||||||
|
'cancel',
|
||||||
|
],
|
||||||
|
closeable: 'esc,close',
|
||||||
|
hasMask: true,
|
||||||
|
align: 'cc cc',
|
||||||
|
minMargin: 40,
|
||||||
|
visible: {
|
||||||
|
type: 'JSExpression',
|
||||||
|
value: 'this.state.isShowDialog',
|
||||||
|
},
|
||||||
|
title: '标题',
|
||||||
|
events: [],
|
||||||
|
__events: [
|
||||||
|
{
|
||||||
|
type: 'componentEvent',
|
||||||
|
name: 'onCancel',
|
||||||
|
relatedEventName: 'closeDialog',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'componentEvent',
|
||||||
|
name: 'onClose',
|
||||||
|
relatedEventName: 'closeDialog',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'componentEvent',
|
||||||
|
name: 'onOk',
|
||||||
|
relatedEventName: 'testFunc',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
onCancel: {
|
||||||
|
type: 'JSFunction',
|
||||||
|
value: 'function(){ this.closeDialog() }',
|
||||||
|
},
|
||||||
|
onClose: {
|
||||||
|
type: 'JSFunction',
|
||||||
|
value: 'function(){ this.closeDialog() }',
|
||||||
|
},
|
||||||
|
onOk: {
|
||||||
|
type: 'JSFunction',
|
||||||
|
value: 'function(){ this.testFunc() }',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: 'Form',
|
||||||
|
id: 'node_dockd5nrh9pi',
|
||||||
|
props: {
|
||||||
|
inline: false,
|
||||||
|
labelAlign: 'top',
|
||||||
|
labelTextAlign: 'right',
|
||||||
|
size: 'medium',
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: 'Form.Item',
|
||||||
|
id: 'node_dockd5nrh9pj',
|
||||||
|
props: {
|
||||||
|
style: {
|
||||||
|
marginBottom: '0',
|
||||||
|
minWidth: '200px',
|
||||||
|
minHeight: '28px',
|
||||||
|
},
|
||||||
|
label: '商品类目',
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: 'Select',
|
||||||
|
id: 'node_dockd5nrh9pk',
|
||||||
|
props: {
|
||||||
|
mode: 'single',
|
||||||
|
hasArrow: true,
|
||||||
|
cacheValue: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'Form.Item',
|
||||||
|
id: 'node_dockd5nrh9pl',
|
||||||
|
props: {
|
||||||
|
style: {
|
||||||
|
marginBottom: '0',
|
||||||
|
minWidth: '200px',
|
||||||
|
minHeight: '28px',
|
||||||
|
},
|
||||||
|
label: '商品类目',
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: 'Select',
|
||||||
|
id: 'node_dockd5nrh9pm',
|
||||||
|
props: {
|
||||||
|
mode: 'single',
|
||||||
|
hasArrow: true,
|
||||||
|
cacheValue: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'Form.Item',
|
||||||
|
id: 'node_dockd5nrh9pn',
|
||||||
|
props: {
|
||||||
|
style: {
|
||||||
|
marginBottom: '0',
|
||||||
|
minWidth: '200px',
|
||||||
|
minHeight: '28px',
|
||||||
|
},
|
||||||
|
label: '商品类目',
|
||||||
|
asterisk: true,
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: 'Select',
|
||||||
|
id: 'node_dockd5nrh9po',
|
||||||
|
props: {
|
||||||
|
mode: 'single',
|
||||||
|
hasArrow: true,
|
||||||
|
cacheValue: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'Form.Item',
|
||||||
|
id: 'node_dockd5nrh9pp',
|
||||||
|
props: {
|
||||||
|
style: {
|
||||||
|
marginBottom: '0',
|
||||||
|
minWidth: '200px',
|
||||||
|
minHeight: '28px',
|
||||||
|
},
|
||||||
|
label: '商品类目',
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: 'Input',
|
||||||
|
id: 'node_dockd5nrh9pr',
|
||||||
|
props: {
|
||||||
|
hasBorder: true,
|
||||||
|
size: 'medium',
|
||||||
|
autoComplete: 'off',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'ErrorComponent',
|
||||||
|
id: 'node_dockd5nrh9pr',
|
||||||
|
props: {
|
||||||
|
name: 'error',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
File diff suppressed because it is too large
Load Diff
324
packages/renderer-core/test/renderer/renderer.test.tsx
Normal file
324
packages/renderer-core/test/renderer/renderer.test.tsx
Normal file
@ -0,0 +1,324 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import renderer from 'react-test-renderer';
|
||||||
|
import schema from '../fixtures/schema/basic';
|
||||||
|
import '../utils/mock-react-render';
|
||||||
|
import rendererFactory from '../../src/renderer/renderer';
|
||||||
|
import components from '../utils/components';
|
||||||
|
|
||||||
|
const Renderer = rendererFactory();
|
||||||
|
|
||||||
|
function getComp(schema, comp = null): Promise<{
|
||||||
|
component,
|
||||||
|
inst,
|
||||||
|
}> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const component = renderer.create(
|
||||||
|
// @ts-ignore
|
||||||
|
<Renderer
|
||||||
|
schema={schema}
|
||||||
|
components={components}
|
||||||
|
/>);
|
||||||
|
|
||||||
|
const componentInstance = component.root;
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
resolve({
|
||||||
|
inst: comp ? componentInstance.findAllByType(comp) : null,
|
||||||
|
component,
|
||||||
|
});
|
||||||
|
}, 20);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
let componentSnapshot;
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
if (componentSnapshot) {
|
||||||
|
let tree = componentSnapshot.toJSON();
|
||||||
|
expect(tree).toMatchSnapshot();
|
||||||
|
componentSnapshot = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Base Render', () => {
|
||||||
|
it('renderComp', () => {
|
||||||
|
const content = (
|
||||||
|
// @ts-ignore
|
||||||
|
<Renderer
|
||||||
|
schema={schema}
|
||||||
|
components={components}
|
||||||
|
/>);
|
||||||
|
const tree = renderer.create(content).toJSON();
|
||||||
|
expect(tree).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('JSExpression', () => {
|
||||||
|
it('base props', (done) => {
|
||||||
|
const schema = {
|
||||||
|
componentName: 'Page',
|
||||||
|
props: {},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: "Div",
|
||||||
|
props: {
|
||||||
|
className: 'div-ut',
|
||||||
|
text: "123",
|
||||||
|
visible: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
getComp(schema, components.Div).then(({ component, inst }) => {
|
||||||
|
expect(inst[0].props.text).toBe('123');
|
||||||
|
expect(inst[0].props.visible).toBeTruthy();
|
||||||
|
|
||||||
|
componentSnapshot = component;
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('JSExpression props', (done) => {
|
||||||
|
const schema = {
|
||||||
|
componentName: 'Page',
|
||||||
|
props: {},
|
||||||
|
state: {
|
||||||
|
isShowDialog: true,
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: "Div",
|
||||||
|
props: {
|
||||||
|
className: "div-ut",
|
||||||
|
visible: {
|
||||||
|
type: 'JSExpression',
|
||||||
|
value: 'this.state.isShowDialog',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
getComp(schema, components.Div).then(({ component, inst }) => {
|
||||||
|
expect(inst[0].props.visible).toBeTruthy();
|
||||||
|
componentSnapshot = component;
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('JSExpression props with loop', (done) => {
|
||||||
|
const schema = {
|
||||||
|
componentName: 'Page',
|
||||||
|
props: {},
|
||||||
|
state: {
|
||||||
|
isShowDialog: true,
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: "Div",
|
||||||
|
loop: [
|
||||||
|
{
|
||||||
|
name: '1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '2'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
props: {
|
||||||
|
className: "div-ut",
|
||||||
|
name1: {
|
||||||
|
type: 'JSExpression',
|
||||||
|
value: 'this.item.name',
|
||||||
|
},
|
||||||
|
name2: {
|
||||||
|
type: 'JSExpression',
|
||||||
|
value: 'item.name',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
getComp(schema, components.Div).then(({ component, inst }) => {
|
||||||
|
// expect(inst[0].props.visible).toBeTruthy();
|
||||||
|
expect(inst.length).toEqual(2);
|
||||||
|
[1, 2].forEach((i) => {
|
||||||
|
expect(inst[0].props[`name${i}`]).toBe('1');
|
||||||
|
expect(inst[1].props[`name${i}`]).toBe('2');
|
||||||
|
})
|
||||||
|
componentSnapshot = component;
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('JSFunction props with loop', (done) => {
|
||||||
|
const schema = {
|
||||||
|
componentName: 'Page',
|
||||||
|
props: {},
|
||||||
|
state: {
|
||||||
|
isShowDialog: true,
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: "Div",
|
||||||
|
loop: [
|
||||||
|
{
|
||||||
|
name: '1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '2'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
props: {
|
||||||
|
className: "div-ut",
|
||||||
|
onClick1: {
|
||||||
|
type: 'JSFunction',
|
||||||
|
value: '() => this.item.name',
|
||||||
|
},
|
||||||
|
onClick2: {
|
||||||
|
type: 'JSFunction',
|
||||||
|
value: 'function(){ return this.item.name }',
|
||||||
|
},
|
||||||
|
onClick3: {
|
||||||
|
type: 'JSFunction',
|
||||||
|
value: 'function(){ return item.name }',
|
||||||
|
},
|
||||||
|
onClick4: {
|
||||||
|
type: 'JSFunction',
|
||||||
|
value: '() => item.name',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
getComp(schema, components.Div).then(({ component, inst }) => {
|
||||||
|
// expect(inst[0].props.visible).toBeTruthy();
|
||||||
|
expect(inst.length).toEqual(2);
|
||||||
|
[1, 2, 3, 4].forEach((i) => {
|
||||||
|
expect(inst[0].props[`onClick${i}`]()).toBe('1');
|
||||||
|
expect(inst[1].props[`onClick${i}`]()).toBe('2');
|
||||||
|
})
|
||||||
|
componentSnapshot = component;
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('JSFunction props', (done) => {
|
||||||
|
const schema = {
|
||||||
|
componentName: 'Page',
|
||||||
|
props: {},
|
||||||
|
state: {
|
||||||
|
isShowDialog: true,
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: "Div",
|
||||||
|
props: {
|
||||||
|
className: "div-ut",
|
||||||
|
onClick: {
|
||||||
|
type: 'JSExpression',
|
||||||
|
value: '() => this.state.isShowDialog',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
getComp(schema, components.Div).then(({ component, inst }) => {
|
||||||
|
expect(!!inst[0].props.onClick).toBeTruthy();
|
||||||
|
expect(inst[0].props.onClick()).toBeTruthy();
|
||||||
|
|
||||||
|
componentSnapshot = component;
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('JSSlot has loop', (done) => {
|
||||||
|
const schema = {
|
||||||
|
componentName: "Page",
|
||||||
|
props: {},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: "SlotComponent",
|
||||||
|
id: "node_k8bnubvz",
|
||||||
|
props: {
|
||||||
|
mobileSlot: {
|
||||||
|
type: "JSSlot",
|
||||||
|
title: "mobile容器",
|
||||||
|
name: "mobileSlot",
|
||||||
|
value: [
|
||||||
|
{
|
||||||
|
condition: true,
|
||||||
|
hidden: false,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
condition: true,
|
||||||
|
hidden: false,
|
||||||
|
loopArgs: [
|
||||||
|
"item",
|
||||||
|
"index"
|
||||||
|
],
|
||||||
|
isLocked: false,
|
||||||
|
conditionGroup: "",
|
||||||
|
componentName: "Text",
|
||||||
|
id: "node_ocl1ao1o7w4",
|
||||||
|
title: "",
|
||||||
|
props: {
|
||||||
|
maxLine: 0,
|
||||||
|
showTitle: false,
|
||||||
|
className: "text_l1ao7pfb",
|
||||||
|
behavior: "NORMAL",
|
||||||
|
content: "这是一个低代码业务组件~",
|
||||||
|
__style__: ":root {\n font-size: 14px;\n color: #666;\n}",
|
||||||
|
fieldId: "text_l1ao7lvp"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
loop: {
|
||||||
|
type: "JSExpression",
|
||||||
|
value: "state.content"
|
||||||
|
},
|
||||||
|
loopArgs: [
|
||||||
|
"item",
|
||||||
|
"index"
|
||||||
|
],
|
||||||
|
isLocked: false,
|
||||||
|
conditionGroup: "",
|
||||||
|
componentName: "Div",
|
||||||
|
id: "node_ocl1ao1o7w3",
|
||||||
|
title: "",
|
||||||
|
props: {
|
||||||
|
useFieldIdAsDomId: false,
|
||||||
|
customClassName: "",
|
||||||
|
className: "div_l1ao7pfc",
|
||||||
|
behavior: "NORMAL",
|
||||||
|
__style__: ":root {\n padding: 12px;\n background: #f2f2f2;\n border: 1px solid #ddd;\n}",
|
||||||
|
fieldId: "div_l1ao7lvq"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
],
|
||||||
|
state: {
|
||||||
|
content: {
|
||||||
|
type: "JSExpression",
|
||||||
|
value: "[{}, {}, {}]",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
getComp(schema, components.Div).then(({ component, inst }) => {
|
||||||
|
expect(inst.length).toBe(3);
|
||||||
|
componentSnapshot = component;
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
})
|
||||||
28
packages/renderer-core/test/utils/components.tsx
Normal file
28
packages/renderer-core/test/utils/components.tsx
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import { Box, Breadcrumb, Form, Select, Input, Button, Table, Pagination, Dialog } from '@alifd/next';
|
||||||
|
|
||||||
|
const Div = (props: any) => (<div {...props}>{props.children}</div>);
|
||||||
|
|
||||||
|
const Text = (props: any) => (<div>{props.content}</div>);
|
||||||
|
|
||||||
|
const SlotComponent = (props: any) => props.mobileSlot;
|
||||||
|
|
||||||
|
const components = {
|
||||||
|
Box,
|
||||||
|
Breadcrumb,
|
||||||
|
'Breadcrumb.Item': Breadcrumb.Item,
|
||||||
|
Form,
|
||||||
|
'Form.Item': Form.Item,
|
||||||
|
Select,
|
||||||
|
Input,
|
||||||
|
Button,
|
||||||
|
'Button.Group': Button.Group,
|
||||||
|
Table,
|
||||||
|
Pagination,
|
||||||
|
Dialog,
|
||||||
|
ErrorComponent: Select,
|
||||||
|
Div,
|
||||||
|
SlotComponent,
|
||||||
|
Text,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default components;
|
||||||
66
packages/renderer-core/test/utils/mock-react-render.ts
Normal file
66
packages/renderer-core/test/utils/mock-react-render.ts
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
import React, { Component, PureComponent, createElement, createContext, forwardRef, ReactInstance, ContextType } from 'react';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
|
import {
|
||||||
|
adapter,
|
||||||
|
pageRendererFactory,
|
||||||
|
componentRendererFactory,
|
||||||
|
blockRendererFactory,
|
||||||
|
addonRendererFactory,
|
||||||
|
tempRendererFactory,
|
||||||
|
rendererFactory,
|
||||||
|
types,
|
||||||
|
} from '../../src';
|
||||||
|
import ConfigProvider from '@alifd/next/lib/config-provider';
|
||||||
|
|
||||||
|
window.React = React;
|
||||||
|
(window as any).ReactDom = ReactDOM;
|
||||||
|
|
||||||
|
adapter.setRuntime({
|
||||||
|
Component,
|
||||||
|
PureComponent,
|
||||||
|
createContext,
|
||||||
|
createElement,
|
||||||
|
forwardRef,
|
||||||
|
findDOMNode: ReactDOM.findDOMNode,
|
||||||
|
});
|
||||||
|
|
||||||
|
adapter.setRenderers({
|
||||||
|
PageRenderer: pageRendererFactory(),
|
||||||
|
ComponentRenderer: componentRendererFactory(),
|
||||||
|
BlockRenderer: blockRendererFactory(),
|
||||||
|
AddonRenderer: addonRendererFactory(),
|
||||||
|
TempRenderer: tempRendererFactory(),
|
||||||
|
DivRenderer: blockRendererFactory(),
|
||||||
|
});
|
||||||
|
|
||||||
|
adapter.setConfigProvider(ConfigProvider);
|
||||||
|
|
||||||
|
function factory() {
|
||||||
|
const Renderer = rendererFactory();
|
||||||
|
return class ReactRenderer extends Renderer implements Component {
|
||||||
|
readonly props: types.IProps;
|
||||||
|
|
||||||
|
context: ContextType<any>;
|
||||||
|
|
||||||
|
setState: (
|
||||||
|
state: types.IState,
|
||||||
|
callback?: () => void,
|
||||||
|
) => void;
|
||||||
|
|
||||||
|
forceUpdate: (callback?: () => void) => void;
|
||||||
|
|
||||||
|
refs: {
|
||||||
|
[key: string]: ReactInstance,
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(props: types.IProps, context: ContextType<any>) {
|
||||||
|
super(props, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
isValidComponent(obj: any) {
|
||||||
|
return obj?.prototype?.isReactComponent || obj?.prototype instanceof Component;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default factory();
|
||||||
@ -8,7 +8,9 @@ export interface Package { // 应该被编辑器默认加载,定义组件大
|
|||||||
urls?: string[] | any; // 组件渲染态视图打包后的 CDN url 列表,包含 js 和 css
|
urls?: string[] | any; // 组件渲染态视图打包后的 CDN url 列表,包含 js 和 css
|
||||||
editUrls?: string[] | any; // 组件编辑态视图打包后的 CDN url 列表,包含 js 和 css
|
editUrls?: string[] | any; // 组件编辑态视图打包后的 CDN url 列表,包含 js 和 css
|
||||||
library: string; // 作为全局变量引用时的名称,和webpack output.library字段含义一样,用来定义全局变量名
|
library: string; // 作为全局变量引用时的名称,和webpack output.library字段含义一样,用来定义全局变量名
|
||||||
async?: boolean,
|
async?: boolean;
|
||||||
|
exportMode?: string;
|
||||||
|
exportSourceLibrary?: any;
|
||||||
exportName?: string;
|
exportName?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
6
packages/utils/build.test.json
Normal file
6
packages/utils/build.test.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"plugins": [
|
||||||
|
"build-plugin-component",
|
||||||
|
"@ali/lowcode-test-mate/plugin/index.ts"
|
||||||
|
]
|
||||||
|
}
|
||||||
14
packages/utils/jest.config.js
Normal file
14
packages/utils/jest.config.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
const esModules = ['@recore/obx-react'].join('|');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
transformIgnorePatterns: [
|
||||||
|
`/node_modules/(?!${esModules})/`,
|
||||||
|
],
|
||||||
|
moduleFileExtensions: ['ts', 'tsx', 'js', 'json'],
|
||||||
|
collectCoverage: true,
|
||||||
|
collectCoverageFrom: [
|
||||||
|
'src/**/*.{ts,tsx}',
|
||||||
|
'!**/node_modules/**',
|
||||||
|
'!**/vendor/**',
|
||||||
|
],
|
||||||
|
};
|
||||||
@ -9,6 +9,7 @@
|
|||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"module": "es/index.js",
|
"module": "es/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"test": "build-scripts test --config build.test.json",
|
||||||
"build": "build-scripts build --skip-demo"
|
"build": "build-scripts build --skip-demo"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@ -320,18 +320,22 @@ export class AssetLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async loadAsyncLibrary(asyncLibraryMap) {
|
private async loadAsyncLibrary(asyncLibraryMap) {
|
||||||
const promiseList = []; const libraryKeyList = [];
|
const promiseList = [];
|
||||||
|
const libraryKeyList = [];
|
||||||
|
const pkgs = [];
|
||||||
for (const key in asyncLibraryMap) {
|
for (const key in asyncLibraryMap) {
|
||||||
// 需要异步加载
|
// 需要异步加载
|
||||||
if (asyncLibraryMap[key].async) {
|
if (asyncLibraryMap[key].async) {
|
||||||
promiseList.push(window[asyncLibraryMap[key].library]);
|
promiseList.push(window[asyncLibraryMap[key].library]);
|
||||||
libraryKeyList.push(asyncLibraryMap[key].library);
|
libraryKeyList.push(asyncLibraryMap[key].library);
|
||||||
|
pkgs.push(asyncLibraryMap[key]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await Promise.all(promiseList).then((mods) => {
|
await Promise.all(promiseList).then((mods) => {
|
||||||
if (mods.length > 0) {
|
if (mods.length > 0) {
|
||||||
mods.map((item, index) => {
|
mods.map((item, index) => {
|
||||||
window[libraryKeyList[index]] = item;
|
const { exportMode, exportSourceLibrary, library } = pkgs[index];
|
||||||
|
window[libraryKeyList[index]] = exportMode === 'functionCall' && (exportSourceLibrary == null || exportSourceLibrary === library) ? item() : item;
|
||||||
return item;
|
return item;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,7 +26,7 @@ export function compatibleLegaoSchema(props: any): any {
|
|||||||
type: 'JSSlot',
|
type: 'JSSlot',
|
||||||
title: (props.value.props as any)?.slotTitle,
|
title: (props.value.props as any)?.slotTitle,
|
||||||
name: (props.value.props as any)?.slotName,
|
name: (props.value.props as any)?.slotName,
|
||||||
value: props.value.children,
|
value: compatibleLegaoSchema(props.value.children),
|
||||||
params: (props.value.props as any)?.slotParams,
|
params: (props.value.props as any)?.slotParams,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
23
packages/utils/test/src/__snapshots__/schema.test.ts.snap
Normal file
23
packages/utils/test/src/__snapshots__/schema.test.ts.snap
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`Schema Ut props 1`] = `
|
||||||
|
Object {
|
||||||
|
"props": Object {
|
||||||
|
"mobileSlot": Object {
|
||||||
|
"name": undefined,
|
||||||
|
"params": undefined,
|
||||||
|
"title": undefined,
|
||||||
|
"type": "JSSlot",
|
||||||
|
"value": Array [
|
||||||
|
Object {
|
||||||
|
"loop": Object {
|
||||||
|
"mock": undefined,
|
||||||
|
"type": "JSExpression",
|
||||||
|
"value": "props.content",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`;
|
||||||
27
packages/utils/test/src/schema.test.ts
Normal file
27
packages/utils/test/src/schema.test.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import { compatibleLegaoSchema } from '../../src/schema';
|
||||||
|
describe('Schema Ut', () => {
|
||||||
|
it('props', () => {
|
||||||
|
const schema = {
|
||||||
|
props: {
|
||||||
|
mobileSlot: {
|
||||||
|
type: "JSBlock",
|
||||||
|
value: {
|
||||||
|
componentName: "Slot",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
loop: {
|
||||||
|
variable: "props.content",
|
||||||
|
type: "variable"
|
||||||
|
},
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = compatibleLegaoSchema(schema);
|
||||||
|
expect(result).toMatchSnapshot();
|
||||||
|
expect(result.props.mobileSlot.value[0].loop.type).toBe('JSExpression');
|
||||||
|
});
|
||||||
|
})
|
||||||
Loading…
x
Reference in New Issue
Block a user