fix(utils): isReactComponent not including react.memo

This commit is contained in:
liujuping 2023-04-17 11:31:19 +08:00 committed by 林熠
parent f1ff1a0706
commit 6160056139
8 changed files with 124 additions and 11 deletions

View File

@ -73,7 +73,7 @@ jobs:
package-manager: yarn
annotations: none
cov-utils:
cov-utils:
runs-on: ubuntu-latest
# skip fork's PR, otherwise it fails while making a comment
if: ${{ github.event.pull_request.head.repo.full_name == 'alibaba/lowcode-engine' }}
@ -91,6 +91,6 @@ cov-utils:
- uses: ArtiomTr/jest-coverage-report-action@v2
with:
working-directory: packages/utils
test-script: npm test
test-script: npm test -- --jest-ci --jest-json --jest-coverage --jest-testLocationInResults --jest-outputFile=report.json
package-manager: yarn
annotations: none

View File

@ -43,7 +43,7 @@ jobs:
- name: test
run: cd packages/designer && npm test
editor-skeleton:
test-editor-skeleton:
runs-on: ubuntu-latest
steps:
- name: checkout
@ -57,4 +57,52 @@ jobs:
run: npm i && npm run setup:skip-build
- name: test
run: cd packages/editor-skeleton && npm test
run: cd packages/editor-skeleton && npm test
test-renderer-core:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '14'
- name: install
run: npm i && npm run setup:skip-build
- name: test
run: cd packages/renderer-core && npm test
test-react-simulator-renderer:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '14'
- name: install
run: npm i && npm run setup:skip-build
- name: test
run: cd packages/react-simulator-renderer && npm test
test-utils:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '14'
- name: install
run: npm i && npm run setup:skip-build
- name: test
run: cd packages/utils && npm test

View File

@ -11,6 +11,7 @@ const jestConfig = {
// },
// testMatch: ['(/tests?/.*(test))\\.[jt]s$'],
// testMatch: ['**/*/base.test.tsx'],
// testMatch: ['**/utils/common.test.ts'],
transformIgnorePatterns: [
`/node_modules/(?!${esModules})/`,
],

View File

@ -374,7 +374,7 @@ describe('test parseThisRequiredExpression', () => {
};
const fn = logger.error = jest.fn();
parseThisRequiredExpression(mockExpression, { state: { text: 'text' } });
expect(fn).toBeCalledWith('parseExpression.error', new ReferenceError('state is not defined'), {"type": "JSExpression", "value": "state.text"}, {"state": {"text": "text"}});
expect(fn).toBeCalledWith(' parseExpression.error', new ReferenceError('state is not defined'), {"type": "JSExpression", "value": "state.text"}, {"state": {"text": "text"}});
});
it('[success] JSExpression handle without this use scopeValue', () => {

View File

@ -1,9 +1,20 @@
module.exports = {
const fs = require('fs');
const { join } = require('path');
const pkgNames = fs.readdirSync(join('..')).filter(pkgName => !pkgName.startsWith('.'));
const jestConfig = {
moduleFileExtensions: ['ts', 'tsx', 'js', 'json'],
collectCoverage: true,
collectCoverage: false,
collectCoverageFrom: [
'src/**/*.{ts,tsx}',
'src/**/*.ts',
'!src/**/*.d.ts',
'!**/node_modules/**',
'!**/vendor/**',
],
};
// 只对本仓库内的 pkg 做 mapping
jestConfig.moduleNameMapper = {};
jestConfig.moduleNameMapper[`^@alilc/lowcode\\-(${pkgNames.join('|')})$`] = '<rootDir>/../$1/src';
module.exports = jestConfig;

View File

@ -3,6 +3,7 @@ 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 function isReactClass(obj: any): obj is ComponentClass<any> {
return obj && obj.prototype && (obj.prototype.isReactComponent || obj.prototype instanceof Component);
@ -16,8 +17,16 @@ function isForwardRefType(obj: any): boolean {
return obj?.$$typeof && obj?.$$typeof === REACT_FORWARD_REF_TYPE;
}
function isMemoType(obj: any): boolean {
return obj?.$$typeof && obj.$$typeof === REACT_MEMO_TYPE;
}
export function isReactComponent(obj: any): obj is ComponentType<any> {
return obj && (isReactClass(obj) || typeof obj === 'function' || isForwardRefType(obj));
if (!obj) {
return false;
}
return Boolean(isReactClass(obj) || typeof obj === 'function' || isForwardRefType(obj) || isMemoType(obj));
}
export function wrapReactClass(view: FunctionComponent) {

View File

@ -309,8 +309,14 @@ describe('build-component', () => {
))
.toEqual({
Button: {
componentName: 'Component',
schema: {},
componentsMap: [],
componentsTree: [
{
componentName: 'Component',
schema: {},
}
],
version: "",
},
});
})

View File

@ -0,0 +1,38 @@
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');
})
})