diff --git a/__tests__/jest.setup.js b/__tests__/jest.setup.js
new file mode 100644
index 000000000..fa9711707
--- /dev/null
+++ b/__tests__/jest.setup.js
@@ -0,0 +1,17 @@
+const originalWarn = console.warn.bind(console.warn);
+global.beforeAll(() => {
+ console.warn = msg => {
+ // warning 先关了,实在太吵。
+ // const str = msg.toString();
+ // if (
+ // str.includes('componentWillMount') ||
+ // str.includes('componentWillReceiveProps')
+ // ) {
+ // return;
+ // }
+ // originalWarn(msg);
+ };
+});
+global.afterAll(() => {
+ console.warn = originalWarn;
+});
diff --git a/__tests__/renderers/Form/__snapshots__/city.test.tsx.snap b/__tests__/renderers/Form/__snapshots__/city.test.tsx.snap
index d7476c8fa..db0318e22 100644
--- a/__tests__/renderers/Form/__snapshots__/city.test.tsx.snap
+++ b/__tests__/renderers/Form/__snapshots__/city.test.tsx.snap
@@ -15,7 +15,9 @@ exports[`Renderer:city 1`] = `
- The form
+
+ The form
+
@@ -28,6 +30,7 @@ exports[`Renderer:city 1`] = `
>
+ >
+
+
+ >
+
+
diff --git a/__tests__/renderers/Form/city.test.tsx b/__tests__/renderers/Form/city.test.tsx
index 8ce5db202..32763c7e8 100644
--- a/__tests__/renderers/Form/city.test.tsx
+++ b/__tests__/renderers/Form/city.test.tsx
@@ -1,38 +1,40 @@
import React = require('react');
import {render, fireEvent} from 'react-testing-library';
import '../../../src/themes/default';
-import {
- render as amisRender
-} from '../../../src/index';
-import { makeEnv } from '../../helper';
+import {render as amisRender} from '../../../src/index';
+import {makeEnv, wait} from '../../helper';
test('Renderer:city', async () => {
- const {
- container,
- getByText
- } = render(amisRender({
+ const {container, getByText} = render(
+ amisRender(
+ {
type: 'form',
api: '/api/xxx',
controls: [
- {
- type: 'city',
- name: 'a',
- label: 'city',
- allowDistrict: true,
- allowCity: true
- }
+ {
+ type: 'city',
+ name: 'a',
+ label: 'city',
+ allowDistrict: true,
+ allowCity: true
+ }
],
title: 'The form',
actions: []
- }, {}, makeEnv({
- })));
+ },
+ {},
+ makeEnv({})
+ )
+ );
- fireEvent.click(getByText('请选择'));
- fireEvent.click(getByText('北京市'));
- fireEvent.click(getByText('请选择'));
- fireEvent.click(getByText('北京市市辖区'));
- fireEvent.click(getByText('请选择'));
- fireEvent.click(getByText('东城区'));
+ await wait(200);
- expect(container).toMatchSnapshot();
-});
\ No newline at end of file
+ fireEvent.click(getByText('请选择'));
+ fireEvent.click(getByText('北京市'));
+ fireEvent.click(getByText('请选择'));
+ fireEvent.click(getByText('北京市市辖区'));
+ fireEvent.click(getByText('请选择'));
+ fireEvent.click(getByText('东城区'));
+
+ expect(container).toMatchSnapshot();
+});
diff --git a/__tests__/stores/service.test.ts b/__tests__/stores/service.test.ts
index 211894758..5cc6516b3 100644
--- a/__tests__/stores/service.test.ts
+++ b/__tests__/stores/service.test.ts
@@ -1,73 +1,95 @@
-import { getSnapshot, getEnv, onSnapshot } from 'mobx-state-tree';
-import { ServiceStore } from '../../src/store/service';
-import { RendererStore } from '../../src/store';
+import {getSnapshot, getEnv, onSnapshot} from 'mobx-state-tree';
+import {StoreNode} from '../../src/store/node';
+import {ServiceStore} from '../../src/store/service';
+import {RendererStore} from '../../src/store';
import omit = require('lodash/omit');
-
test('store:ServiceStore', () => {
- const store = ServiceStore.create({
- id: '1',
- storeType: ServiceStore.name
- });
+ const store = ServiceStore.create({
+ id: '1',
+ storeType: ServiceStore.name
+ });
- expect(getSnapshot(store)).toMatchSnapshot();
+ expect(getSnapshot(store)).toMatchSnapshot();
});
-
test('store:ServiceStore fetchInitData success', async () => {
- const fetcher = jest.fn().mockImplementationOnce(() => Promise.resolve({
- ok: true,
- data: {
- a: 1,
- b: 2
- }
- }));
- const mainStore = RendererStore.create({}, {
- fetcher
- });
- const states:Array = [];
+ const fetcher = jest.fn().mockImplementationOnce(() =>
+ Promise.resolve({
+ ok: true,
+ data: {
+ a: 1,
+ b: 2
+ }
+ })
+ );
+ const isCancel = jest.fn(() => false);
+ const mainStore = RendererStore.create(
+ {},
+ {
+ fetcher,
+ isCancel
+ }
+ );
+ const states: Array = [];
+ const store = ServiceStore.create(
+ {
+ id: '1',
+ storeType: ServiceStore.name
+ },
+ {
+ fetcher,
+ isCancel
+ }
+ );
+ mainStore.addStore(store);
- const store = ServiceStore.create({
- id: '1',
- storeType: ServiceStore.name
- });
- mainStore.addStore(store);
+ onSnapshot(store, snapshot => states.push(snapshot));
- onSnapshot(store, (snapshot) => states.push(snapshot));
+ await store.fetchInitData('/api/xxx');
- await store.fetchInitData('/api/xxx');
+ const ignoreUdatedAt = states.map(snapshot => omit(snapshot, ['updatedAt']));
+ expect(ignoreUdatedAt).toMatchSnapshot();
- const ignoreUdatedAt = states.map(snapshot => omit(snapshot, ['updatedAt']));
- expect(ignoreUdatedAt).toMatchSnapshot();
-
- expect(states.length).toBe(2);
- expect(states[1].updatedAt).not.toEqual(states[0].updatedAt);
+ expect(states.length).toBe(2);
+ expect(states[1].updatedAt).not.toEqual(states[0].updatedAt);
});
test('store:ServiceStore fetchInitData failed', async () => {
- const fetcher = jest.fn().mockImplementationOnce(() => Promise.reject('Network Error'));
- const notify = jest.fn();
- const isCancel = jest.fn(() => false);
- const mainStore = RendererStore.create({}, {
- fetcher,
- notify,
- isCancel
- });
- const states:Array = [];
+ const fetcher = jest
+ .fn()
+ .mockImplementationOnce(() => Promise.reject('Network Error'));
+ const notify = jest.fn();
+ const isCancel = jest.fn(() => false);
+ const mainStore = RendererStore.create(
+ {},
+ {
+ fetcher,
+ notify,
+ isCancel
+ }
+ );
+ const states: Array = [];
+ const store = ServiceStore.create(
+ {
+ id: '1',
+ storeType: ServiceStore.name
+ },
+ {
+ fetcher,
+ notify,
+ isCancel
+ }
+ );
+ mainStore.addStore(store);
- const store = ServiceStore.create({
- id: '1',
- storeType: ServiceStore.name
- });
- mainStore.addStore(store);
+ onSnapshot(store, snapshot => states.push(snapshot));
- onSnapshot(store, (snapshot) => states.push(snapshot));
-
- await store.fetchInitData('/api/xxx');
- expect(states).toMatchSnapshot();
- expect(notify).toHaveBeenCalled();
- expect(notify).toHaveBeenLastCalledWith("error", "Network Error");
- expect(isCancel).toHaveBeenCalled();
-});
\ No newline at end of file
+ await store.fetchInitData('/api/xxx');
+ expect(states).toMatchSnapshot();
+ expect(notify).toHaveBeenCalled();
+ expect(notify).toHaveBeenLastCalledWith('error', 'Network Error');
+ expect(isCancel).toHaveBeenCalled();
+});
diff --git a/fis-conf.js b/fis-conf.js
index 7d81fbb6e..42f5029cf 100644
--- a/fis-conf.js
+++ b/fis-conf.js
@@ -110,24 +110,23 @@ fis.match('/docs/**.md', {
parser: [
parserMarkdown,
function (contents, file) {
- return contents.replace(/\bhref=\\('|")(.+?)\\\1/g, function (
- _,
- quota,
- link
- ) {
- if (/\.md($|#)/.test(link) && !/^https?\:/.test(link)) {
- let parts = link.split('#');
- parts[0] = parts[0].replace('.md', '');
+ return contents.replace(
+ /\bhref=\\('|")(.+?)\\\1/g,
+ function (_, quota, link) {
+ if (/\.md($|#)/.test(link) && !/^https?\:/.test(link)) {
+ let parts = link.split('#');
+ parts[0] = parts[0].replace('.md', '');
- if (parts[0][0] !== '/') {
- parts[0] = path.resolve(path.dirname(file.subpath), parts[0]);
+ if (parts[0][0] !== '/') {
+ parts[0] = path.resolve(path.dirname(file.subpath), parts[0]);
+ }
+
+ return 'href=\\' + quota + parts.join('#') + '\\' + quota;
}
- return 'href=\\' + quota + parts.join('#') + '\\' + quota;
+ return _;
}
-
- return _;
- });
+ );
}
],
isMod: true
@@ -170,7 +169,14 @@ fis.match('{*.ts,*.jsx,*.tsx,/src/**.js,/src/**.ts}', {
}),
function (content) {
- return content.replace(/\b[a-zA-Z_0-9$]+\.__uri\s*\(/g, '__uri(');
+ return content
+ .replace(/\b[a-zA-Z_0-9$]+\.__uri\s*\(/g, '__uri(')
+ .replace(
+ /return\s+(tslib_\d+)\.__importStar\(require\(('|")(.*?)\2\)\);/g,
+ function (_, tslib, quto, value) {
+ return `return new Promise(function(resolve){require(['${value}'], function(ret) {resolve(${tslib}.__importStar(ret));})});`;
+ }
+ );
}
],
preprocessor: fis.plugin('js-require-css'),
@@ -239,19 +245,26 @@ if (fis.project.currentMedia() === 'publish') {
allowUmdGlobalAccess: true
}),
function (contents) {
- return contents.replace(
- /(?:\w+\.)?\b__uri\s*\(\s*('|")(.*?)\1\s*\)/g,
- function (_, quote, value) {
- let str = quote + value + quote;
- return (
- '(function(){try {return __uri(' +
- str +
- ')} catch(e) {return ' +
- str +
- '}})()'
- );
- }
- );
+ return contents
+ .replace(
+ /(?:\w+\.)?\b__uri\s*\(\s*('|")(.*?)\1\s*\)/g,
+ function (_, quote, value) {
+ let str = quote + value + quote;
+ return (
+ '(function(){try {return __uri(' +
+ str +
+ ')} catch(e) {return ' +
+ str +
+ '}})()'
+ );
+ }
+ )
+ .replace(
+ /return\s+(tslib_\d+)\.__importStar\(require\(('|")(.*?)\2\)\);/g,
+ function (_, tslib, quto, value) {
+ return `return new Promise(function(resolve){require(['${value}'], function(ret) {resolve(${tslib}.__importStar(ret));})});`;
+ }
+ );
}
],
preprocessor: null
@@ -345,9 +358,15 @@ if (fis.project.currentMedia() === 'publish') {
experimentalDecorators: true,
sourceMap: false
}),
-
function (content) {
- return content.replace(/\b[a-zA-Z_0-9$]+\.__uri\s*\(/g, '__uri(');
+ return content
+ .replace(/\b[a-zA-Z_0-9$]+\.__uri\s*\(/g, '__uri(')
+ .replace(
+ /return\s+(tslib_\d+)\.__importStar\(require\(('|")(.*?)\2\)\);/g,
+ function (_, tslib, quto, value) {
+ return `return new Promise(function(resolve){require(['${value}'], function(ret) {resolve(${tslib}.__importStar(ret));})});`;
+ }
+ );
}
],
preprocessor: fis.plugin('js-require-css'),
@@ -521,24 +540,25 @@ if (fis.project.currentMedia() === 'publish') {
parser: [
parserMarkdown,
function (contents, file) {
- return contents.replace(/\bhref=\\('|")(.+?)\\\1/g, function (
- _,
- quota,
- link
- ) {
- if (/\.md($|#)/.test(link) && !/^https?\:/.test(link)) {
- let parts = link.split('#');
- parts[0] = parts[0].replace('.md', '');
+ return contents.replace(
+ /\bhref=\\('|")(.+?)\\\1/g,
+ function (_, quota, link) {
+ if (/\.md($|#)/.test(link) && !/^https?\:/.test(link)) {
+ let parts = link.split('#');
+ parts[0] = parts[0].replace('.md', '');
- if (parts[0][0] !== '/') {
- parts[0] = path.resolve(path.dirname(file.subpath), parts[0]);
+ if (parts[0][0] !== '/') {
+ parts[0] = path.resolve(path.dirname(file.subpath), parts[0]);
+ }
+
+ return (
+ 'href=\\' + quota + '/amis' + parts.join('#') + '\\' + quota
+ );
}
- return 'href=\\' + quota + '/amis' + parts.join('#') + '\\' + quota;
+ return _;
}
-
- return _;
- });
+ );
}
]
});
@@ -658,18 +678,17 @@ if (fis.project.currentMedia() === 'publish') {
DocJs.getContent(),
ExampleJs.getContent()
].join('\n');
- source.replace(/\bpath\b\s*\:\s*('|")(.*?)\1/g, function (
- _,
- qutoa,
- path
- ) {
- if (path === '*') {
- return;
- }
+ source.replace(
+ /\bpath\b\s*\:\s*('|")(.*?)\1/g,
+ function (_, qutoa, path) {
+ if (path === '*') {
+ return;
+ }
- pages.push(path.replace(/^\//, ''));
- return _;
- });
+ pages.push(path.replace(/^\//, ''));
+ return _;
+ }
+ );
const contents = indexHtml.getContent();
pages.forEach(function (path) {
@@ -713,7 +732,30 @@ if (fis.project.currentMedia() === 'publish') {
sourceMap: false,
importHelpers: true,
esModuleInterop: true
- })
+ }),
+
+ function (contents) {
+ return contents
+ .replace(
+ /(?:\w+\.)?\b__uri\s*\(\s*('|")(.*?)\1\s*\)/g,
+ function (_, quote, value) {
+ let str = quote + value + quote;
+ return (
+ '(function(){try {return __uri(' +
+ str +
+ ')} catch(e) {return ' +
+ str +
+ '}})()'
+ );
+ }
+ )
+ .replace(
+ /return\s+(tslib_\d+)\.__importStar\(require\(('|")(.*?)\2\)\);/g,
+ function (_, tslib, quto, value) {
+ return `return new Promise(function(resolve){require(['${value}'], function(ret) {resolve(${tslib}.__importStar(ret));})});`;
+ }
+ );
+ }
]
});
ghPages.match('*', {
diff --git a/package.json b/package.json
index c5292c373..1d101ac65 100644
--- a/package.json
+++ b/package.json
@@ -93,6 +93,7 @@
"@types/async": "^2.0.45",
"@types/classnames": "^2.2.3",
"@types/dom-helpers": "^3.4.1",
+ "@types/echarts": "^4.9.2",
"@types/history": "^4.6.0",
"@types/hoist-non-react-statics": "^3.3.1",
"@types/jest": "^24.9.1",
@@ -183,9 +184,40 @@
"\\.(css|less|sass|scss)$": "/__mocks__/styleMock.js",
"\\.(svg)$": "/__mocks__/svgMock.js"
},
+ "setupFilesAfterEnv": [
+ "/__tests__/jest.setup.js"
+ ],
"globals": {
"ts-jest": {
- "diagnostics": false
+ "diagnostics": false,
+ "tsconfig": {
+ "module": "commonjs",
+ "target": "es5",
+ "lib": [
+ "es6",
+ "dom",
+ "ES2015"
+ ],
+ "sourceMap": true,
+ "jsx": "react",
+ "moduleResolution": "node",
+ "rootDir": ".",
+ "importHelpers": true,
+ "esModuleInterop": true,
+ "allowSyntheticDefaultImports": true,
+ "sourceRoot": ".",
+ "noImplicitReturns": true,
+ "noImplicitThis": true,
+ "noImplicitAny": true,
+ "strictNullChecks": true,
+ "experimentalDecorators": true,
+ "emitDecoratorMetadata": false,
+ "typeRoots": [
+ "./node_modules/@types",
+ "./types"
+ ],
+ "skipLibCheck": true
+ }
}
}
},
diff --git a/scss/components/form/_text.scss b/scss/components/form/_text.scss
index 9510116b1..da09f538a 100644
--- a/scss/components/form/_text.scss
+++ b/scss/components/form/_text.scss
@@ -15,6 +15,7 @@
flex-grow: 1;
line-height: 1;
white-space: nowrap;
+ display: flex;
> input {
display: inline-block;
diff --git a/src/components/Editor.tsx b/src/components/Editor.tsx
index ab5d6b63d..fd070e152 100644
--- a/src/components/Editor.tsx
+++ b/src/components/Editor.tsx
@@ -176,9 +176,7 @@ export class Editor extends React.Component {
}
loadMonaco() {
- (require as any)(['monaco-editor'], (monaco: any) => {
- this.initMonaco(monaco);
- });
+ import('monaco-editor').then(monaco => this.initMonaco(monaco));
}
initMonaco(monaco: any) {
diff --git a/src/components/ResultBox.tsx b/src/components/ResultBox.tsx
index 12846b5da..5509277f0 100644
--- a/src/components/ResultBox.tsx
+++ b/src/components/ResultBox.tsx
@@ -14,7 +14,7 @@ export interface ResultBoxProps
onChange?: (value: string) => void;
onResultClick?: (e: React.MouseEvent) => void;
result?: Array | any;
- itemRender: (value: any) => JSX.Element;
+ itemRender: (value: any) => JSX.Element | string;
onResultChange?: (value: Array) => void;
allowInput?: boolean;
inputPlaceholder: string;
diff --git a/src/components/condition-builder/index.tsx b/src/components/condition-builder/index.tsx
index f8acf9a0b..c5272eb41 100644
--- a/src/components/condition-builder/index.tsx
+++ b/src/components/condition-builder/index.tsx
@@ -67,7 +67,7 @@ export class QueryBuilder extends React.Component {
}
@autobind
- handleDragOver(e: React.DragEvent) {
+ handleDragOver(e: DragEvent) {
e.preventDefault();
const item = (e.target as HTMLElement).closest('[data-id]') as HTMLElement;
diff --git a/src/renderers/CRUD.tsx b/src/renderers/CRUD.tsx
index a4cc58892..6a80b2d9c 100644
--- a/src/renderers/CRUD.tsx
+++ b/src/renderers/CRUD.tsx
@@ -1706,7 +1706,7 @@ export default class CRUD extends React.Component {