├── .gitignore ├── .prettierrc ├── LICENSE ├── README.md ├── example ├── .umirc.js ├── package.json └── src │ ├── _mock.js │ ├── index.css │ ├── index.js │ └── model.js ├── layouts ├── ant-design-pro-user │ ├── index.js │ ├── logo.svg │ └── style.less ├── ant-design-pro │ ├── HeaderDropdown │ │ ├── index.jsx │ │ └── index.less │ ├── SelectLang │ │ ├── index.jsx │ │ └── index.less │ ├── index.js │ └── logo.svg └── blankLayout │ └── index.js ├── package.json └── src ├── index.js ├── mock-request.js └── mock-request.test.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | yarn.lock 3 | package-lock.json 4 | /example/dist 5 | /lib 6 | .umi 7 | .umi-production 8 | yarn-error.log 9 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "overrides": [ 4 | { 5 | "files": ".prettierrc", 6 | "options": { "parser": "json" } 7 | } 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018-present yutingzhao1991 (yutingzhao1991@sina.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # umi-plugin-block-dev 2 | 3 | [![NPM version](https://img.shields.io/npm/v/umi-plugin-block-dev.svg?style=flat)](https://npmjs.org/package/umi-plugin-block-dev) 4 | [![NPM downloads](http://img.shields.io/npm/dm/umi-plugin-block-dev.svg?style=flat)](https://npmjs.org/package/umi-plugin-block-dev) 5 | 6 | A umi plugin for develop a umi block with umi 7 | 8 | ## Layout 9 | 10 | ### blankLayout 11 | 12 | ![image](https://user-images.githubusercontent.com/8186664/59409733-83d23a80-8de9-11e9-9a0b-e41b8b4ce5a8.png) 13 | 14 | ### ant-design-pro 15 | 16 | ![image](https://user-images.githubusercontent.com/8186664/59409669-52f20580-8de9-11e9-8f4f-23ee873efe1b.png) 17 | 18 | ### ant-design-pro-user 19 | 20 | ![image](https://user-images.githubusercontent.com/8186664/59409597-1f16e000-8de9-11e9-8993-e68ec1b4da0e.png) 21 | 22 | ## Usage 23 | 24 | Configure in `.umirc.js`, 25 | 26 | ```js 27 | export default { 28 | plugins: [['umi-plugin-block-dev', options]] 29 | }; 30 | ``` 31 | 32 | And you can use `create-umi` to create a umi block automatically: 33 | 34 | ```sh 35 | $ yarn create umi --block 36 | ``` 37 | 38 | ## options 39 | 40 | ```js 41 | { 42 | layout: 'ant-design-pro', // or ant-design-pro-user 43 | menu: { 44 | name: 'demo', 45 | icon: 'home', 46 | }, 47 | mockUmiRequest: true // whether to build mock data . _mock.js 48 | } 49 | ``` 50 | 51 | ### env 52 | 53 | - BLOCK_DEV_PATH: custom block preview path 54 | - BLOCK_DEV_MOCK_UMI_REQUEST: package mock data to build result, for build static preview site 55 | - BLOCK_PAGES_LAYOUT: custom block Layout 56 | 57 | ## LICENSE 58 | 59 | MIT 60 | -------------------------------------------------------------------------------- /example/.umirc.js: -------------------------------------------------------------------------------- 1 | import { join } from 'path'; 2 | 3 | export default { 4 | plugins: [ 5 | [ 6 | join(__dirname, '..', require('../package').main || 'index.js'), 7 | { 8 | layout: 'ant-design-pro', 9 | menu: { 10 | name: 'demo', 11 | icon: 'home', 12 | }, 13 | mockUmiRequest: true // whether to build mock data . _mock.js \ _mock.ts 14 | } 15 | ], 16 | [ 17 | 'umi-plugin-react', 18 | { 19 | dva: true, 20 | locale: true, 21 | antd: true 22 | } 23 | ] 24 | ] 25 | }; 26 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "version": "1.0.0", 4 | "description": "a example block", 5 | "main": "src/index.js", 6 | "scripts": { 7 | "dev": "umi dev", 8 | "build": "umi build" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "umi": "^2.7.0", 14 | "umi-plugin-react": "^1.8.1" 15 | }, 16 | "dependencies": { 17 | "umi-request": "^1.0.7" 18 | } 19 | } -------------------------------------------------------------------------------- /example/src/_mock.js: -------------------------------------------------------------------------------- 1 | export default { 2 | 'GET /api/test': { 3 | text: 'I am a test block.', 4 | }, 5 | }; 6 | -------------------------------------------------------------------------------- /example/src/index.css: -------------------------------------------------------------------------------- 1 | .normal { 2 | height: 100%; 3 | padding: 80px; 4 | } 5 | -------------------------------------------------------------------------------- /example/src/index.js: -------------------------------------------------------------------------------- 1 | import styles from './index.css'; 2 | import { connect } from 'dva'; 3 | import { formatMessage } from 'umi-plugin-react/locale'; 4 | 5 | import React from 'react'; 6 | 7 | const Welcome = () => ( 8 |
9 | Want to add more pages? Please refer to{' '} 10 | 15 | use block 16 | 17 | {formatMessage({ id: '.', defaultMessage: '.' })} 18 |
19 | ); 20 | 21 | export default connect(({ test }) => ({ 22 | test 23 | }))(Welcome); 24 | -------------------------------------------------------------------------------- /example/src/model.js: -------------------------------------------------------------------------------- 1 | import request from 'umi-request'; 2 | 3 | export default { 4 | namespace: 'test', 5 | state: { 6 | text: 'loading...', 7 | }, 8 | effects: { 9 | *fetch(_, { call, put }) { 10 | const response = yield call(request, '/api/test'); 11 | yield put({ 12 | type: 'save', 13 | payload: response, 14 | }); 15 | }, 16 | }, 17 | reducers: { 18 | save(state, { payload }) { 19 | return { 20 | ...state, 21 | ...payload, 22 | }; 23 | }, 24 | }, 25 | subscriptions: { 26 | setup({ dispatch }) { 27 | dispatch({ type:'fetch' }); 28 | }, 29 | }, 30 | }; 31 | -------------------------------------------------------------------------------- /layouts/ant-design-pro-user/index.js: -------------------------------------------------------------------------------- 1 | import React, { Fragment } from 'react'; 2 | import { formatMessage } from 'umi/locale'; 3 | import Link from 'umi/link'; 4 | import { Icon } from 'antd'; 5 | import logo from './logo.svg'; 6 | import './style.less'; 7 | 8 | const links = [ 9 | { 10 | key: 'help', 11 | title: formatMessage({ id: 'layout.user.link.help' }), 12 | href: '' 13 | }, 14 | { 15 | key: 'privacy', 16 | title: formatMessage({ id: 'layout.user.link.privacy' }), 17 | href: '' 18 | }, 19 | { 20 | key: 'terms', 21 | title: formatMessage({ id: 'layout.user.link.terms' }), 22 | href: '' 23 | } 24 | ]; 25 | 26 | const copyright = ( 27 | 28 | Copyright 2018 蚂蚁金服体验技术部出品 29 | 30 | ); 31 | 32 | class UserLayout extends React.PureComponent { 33 | render() { 34 | const { children } = this.props; 35 | return ( 36 |
37 |
38 |
39 |
40 | 41 | logo 42 | Ant Design 43 | 44 |
45 |
46 | Ant Design 是西湖区最具影响力的 Web 设计规范 47 |
48 |
49 | {children} 50 |
51 |
52 | ); 53 | } 54 | } 55 | 56 | export default UserLayout; 57 | -------------------------------------------------------------------------------- /layouts/ant-design-pro-user/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Group 28 Copy 5 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /layouts/ant-design-pro-user/style.less: -------------------------------------------------------------------------------- 1 | @import '~antd/lib/style/themes/default.less'; 2 | 3 | :global { 4 | .umi-block-dev { 5 | display: flex; 6 | flex-direction: column; 7 | height: 100vh; 8 | overflow: auto; 9 | background: @layout-body-background; 10 | 11 | .lang { 12 | text-align: right; 13 | width: 100%; 14 | height: 40px; 15 | line-height: 44px; 16 | :global(.ant-dropdown-trigger) { 17 | margin-right: 24px; 18 | } 19 | } 20 | 21 | .content { 22 | padding: 32px 0; 23 | flex: 1; 24 | } 25 | 26 | .top { 27 | text-align: center; 28 | } 29 | 30 | .header { 31 | height: 44px; 32 | line-height: 44px; 33 | a { 34 | text-decoration: none; 35 | } 36 | } 37 | 38 | .logo { 39 | height: 44px; 40 | vertical-align: top; 41 | margin-right: 16px; 42 | } 43 | 44 | .title { 45 | font-size: 33px; 46 | color: @heading-color; 47 | font-family: Avenir, 'Helvetica Neue', Arial, Helvetica, sans-serif; 48 | font-weight: 600; 49 | position: relative; 50 | top: 2px; 51 | } 52 | 53 | .desc { 54 | font-size: @font-size-base; 55 | color: @text-color-secondary; 56 | margin-top: 12px; 57 | margin-bottom: 40px; 58 | } 59 | } 60 | 61 | @media (min-width: @screen-md-min) { 62 | .umi-block-dev { 63 | background-image: url('https://gw.alipayobjects.com/zos/rmsportal/TVYTbAXWheQpRcWDaDMu.svg'); 64 | background-repeat: no-repeat; 65 | background-position: center 110px; 66 | background-size: 100%; 67 | 68 | .content { 69 | padding: 32px 0 24px 0; 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /layouts/ant-design-pro/HeaderDropdown/index.jsx: -------------------------------------------------------------------------------- 1 | import { Dropdown } from 'antd'; 2 | import React from 'react'; 3 | import classNames from 'classnames'; 4 | import styles from './index.less'; 5 | 6 | const HeaderDropdown = ({ overlayClassName: cls, ...restProps }) => ( 7 | 11 | ); 12 | 13 | export default HeaderDropdown; 14 | -------------------------------------------------------------------------------- /layouts/ant-design-pro/HeaderDropdown/index.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .container > * { 4 | background-color: #fff; 5 | border-radius: 4px; 6 | box-shadow: @shadow-1-down; 7 | } 8 | 9 | @media screen and (max-width: @screen-xs) { 10 | .container { 11 | width: 100% !important; 12 | } 13 | .container > * { 14 | border-radius: 0 !important; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /layouts/ant-design-pro/SelectLang/index.jsx: -------------------------------------------------------------------------------- 1 | import { Icon, Menu } from 'antd'; 2 | import { getLocale, setLocale } from 'umi-plugin-react/locale'; 3 | import React from 'react'; 4 | import classNames from 'classnames'; 5 | import HeaderDropdown from '../HeaderDropdown'; 6 | import styles from './index.less'; 7 | 8 | const SelectLang = props => { 9 | const { className } = props; 10 | const selectedLang = getLocale(); 11 | const changeLang = ({ key }) => setLocale(key); 12 | const locales = ['zh-CN', 'zh-TW', 'en-US', 'pt-BR']; 13 | const languageLabels = { 14 | 'zh-CN': '简体中文', 15 | 'zh-TW': '繁体中文', 16 | 'en-US': 'English', 17 | 'pt-BR': 'Português' 18 | }; 19 | const languageIcons = { 20 | 'zh-CN': '🇨🇳', 21 | 'zh-TW': '🇭🇰', 22 | 'en-US': '🇬🇧', 23 | 'pt-BR': '🇧🇷' 24 | }; 25 | const langMenu = ( 26 | 31 | {locales.map(locale => ( 32 | 33 | 34 | {languageIcons[locale]} 35 | {' '} 36 | {languageLabels[locale]} 37 | 38 | ))} 39 | 40 | ); 41 | return ( 42 |
48 | 49 | 50 | 51 | 52 | 53 |
54 | ); 55 | }; 56 | 57 | export default SelectLang; 58 | -------------------------------------------------------------------------------- /layouts/ant-design-pro/SelectLang/index.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .menu { 4 | :global(.anticon) { 5 | margin-right: 8px; 6 | } 7 | :global(.ant-dropdown-menu-item) { 8 | min-width: 160px; 9 | } 10 | } 11 | 12 | .dropDown { 13 | line-height: @layout-header-height; 14 | vertical-align: top; 15 | cursor: pointer; 16 | > i { 17 | font-size: 16px !important; 18 | transform: none !important; 19 | svg { 20 | position: relative; 21 | top: -1px; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /layouts/ant-design-pro/index.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import logo from './logo.svg'; 3 | import { BasicLayout, SettingDrawer } from '@ant-design/pro-layout'; 4 | import SelectLang from './SelectLang'; 5 | 6 | export default props => { 7 | const { children } = props; 8 | const [settings, changeSetting] = useState({}); 9 | return ( 10 | 11 | } 16 | > 17 | {children} 18 | 19 | changeSetting(settings)} 22 | /> 23 | 24 | ); 25 | }; 26 | -------------------------------------------------------------------------------- /layouts/ant-design-pro/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Group 28 Copy 5 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 42 | 43 | -------------------------------------------------------------------------------- /layouts/blankLayout/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { BasicLayout } from '@ant-design/pro-layout'; 3 | 4 | const Layout = ({ children }) => ( 5 | 6 | {children} 7 | 8 | ); 9 | 10 | export default Layout; 11 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "umi-plugin-block-dev", 3 | "version": "3.0.3", 4 | "description": "A umi plugin for develop a umi block with umi", 5 | "license": "MIT", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/umijs/umi-plugin-block-dev" 9 | }, 10 | "homepage": "https://github.com/umijs/umi-plugin-block-dev", 11 | "authors": [ 12 | "yutingzhao1991 ", 13 | "chenshuai2144 " 14 | ], 15 | "bugs": { 16 | "url": "https://github.com/umijs/umi-plugin-block-dev/issues" 17 | }, 18 | "peerDependencies": { 19 | "@ant-design/pro-layout": "^4.11.0-1", 20 | "umi": "2.x" 21 | }, 22 | "main": "lib/index.js", 23 | "scripts": { 24 | "build": "umi-tools build", 25 | "prepublishOnly": "umi-tools build", 26 | "pub": "npm run build && npm publish", 27 | "test": "umi-test" 28 | }, 29 | "devDependencies": { 30 | "umi-plugin-react": "^1.9.7", 31 | "umi-request": "^1.0.8", 32 | "umi-test": "^1.2.2", 33 | "umi-tools": "*" 34 | }, 35 | "files": [ 36 | "lib", 37 | "src", 38 | "layouts" 39 | ], 40 | "dependencies": { 41 | "path-to-regexp": "^2.4.0", 42 | "umi": "^2.12.9", 43 | "uppercamelcase": "^3.0.0" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | // ref: 2 | // - https://umijs.org/plugin/develop.html 3 | import { join, dirname } from 'path'; 4 | import { existsSync, readdirSync } from 'fs'; 5 | import assert from 'assert'; 6 | import upperCamelCase from 'uppercamelcase'; 7 | 8 | if (!process.env.PAGES_PATH) { 9 | process.env.PAGES_PATH = 'src'; 10 | } 11 | 12 | const layouts = ['ant-design-pro', 'ant-design-pro-user', 'blankLayout']; 13 | 14 | function findGitDir(thePath) { 15 | if (thePath === '/') { 16 | return null; 17 | } 18 | const items = readdirSync(thePath); 19 | if (items.includes('.git')) { 20 | return thePath; 21 | } else { 22 | return findGitDir(dirname(thePath)); 23 | } 24 | } 25 | 26 | export function getNameFromPkg(pkg) { 27 | if (!pkg.name) { 28 | return null; 29 | } 30 | return pkg.name.split('/').pop(); 31 | } 32 | 33 | export default function(api, options = {}) { 34 | api.registerCommand('block_dev', {}, ({ _ }) => { 35 | process.env.PAGES_PATH = `${_[0]}/src`; 36 | process.env.UMI_UI = 'none'; 37 | require(require.resolve(`umi/lib/scripts/dev`)); 38 | }); 39 | 40 | const { paths, debug } = api; 41 | const path = process.env.BLOCK_DEV_PATH || options.path || '/'; 42 | const blockConfig = require(join(paths.cwd, 'package.json')).blockConfig; 43 | 44 | let subBlocks = []; 45 | 46 | // 支持区块依赖 47 | if (blockConfig && blockConfig.dependencies) { 48 | debug('find dependencies in package.json'); 49 | const gitRoot = findGitDir(paths.cwd); 50 | debug(`get gitRoot: ${gitRoot}`); 51 | if (gitRoot) { 52 | subBlocks = blockConfig.dependencies.map(d => { 53 | const subBlockPath = join(gitRoot, d); 54 | const subBlockConfig = require(join(subBlockPath, 'package.json')); 55 | const subBlockName = upperCamelCase(getNameFromPkg(subBlockConfig)); 56 | return { 57 | name: subBlockName, 58 | path: subBlockPath 59 | }; 60 | }); 61 | } else { 62 | throw new Error('Not find git root, can not use dependencies.'); 63 | } 64 | } 65 | 66 | // 是否 mock 数据,用于测试 67 | const mockUmiRequest = 68 | process.env.BLOCK_DEV_MOCK_UMI_REQUEST === 'true' || 69 | options.mockUmiRequest || 70 | false; 71 | 72 | api.modifyDefaultConfig(memo => { 73 | // 这个环境变量是为了截图的时候可以动态设置 layout 74 | // 所以会优先从 环境变量里面取 75 | const layoutConfig = process.env.BLOCK_PAGES_LAYOUT || options.layout; 76 | 77 | if (layoutConfig) { 78 | assert( 79 | layouts.includes(layoutConfig), 80 | `layout must be one of ${layouts.join(',')}` 81 | ); 82 | const layout = join(__dirname, `../layouts/${layoutConfig}`); 83 | const pathToLayout = (paths.absPagesPath, layout); 84 | return { 85 | ...memo, 86 | routes: [ 87 | { 88 | path: '/', 89 | component: pathToLayout, 90 | routes: [ 91 | { 92 | path, 93 | ...options.menu, 94 | component: './', 95 | exact: false 96 | } 97 | ] 98 | } 99 | ], 100 | extraBabelIncludes: [layout].concat(subBlocks.map(b => b.path)) 101 | }; 102 | } 103 | return { 104 | ...memo, 105 | routes: [ 106 | { 107 | ...options.menu, 108 | path, 109 | component: './', 110 | exact: false 111 | } 112 | ] 113 | }; 114 | }); 115 | 116 | if (mockUmiRequest && existsSync(join(paths.absPagesPath, '_mock.js'))) { 117 | // build mock data to dist, for static block demo 118 | api.addEntryImportAhead({ 119 | source: join(paths.absPagesPath, '_mock.js'), 120 | specifier: '__block_mock' 121 | }); 122 | api.addEntryCodeAhead(` 123 | window.g_block_mock = __block_mock; 124 | `); 125 | api.chainWebpackConfig(webpackConfig => { 126 | webpackConfig.resolve.alias.set( 127 | 'umi-request$', 128 | join(__dirname, 'mock-request.js') 129 | ); 130 | }); 131 | } 132 | api.addHTMLStyle({ 133 | content: ` 134 | body,html,#root{ 135 | height:100% 136 | } 137 | ` 138 | }); 139 | api.chainWebpackConfig(webpackConfig => { 140 | webpackConfig.resolve.alias.set('@', join(paths.absSrcPath, '@')); 141 | subBlocks.forEach(b => { 142 | webpackConfig.resolve.alias.set(`./${b.name}`, join(b.path, 'src')); 143 | }); 144 | }); 145 | } 146 | -------------------------------------------------------------------------------- /src/mock-request.js: -------------------------------------------------------------------------------- 1 | import pathToRegexp from 'path-to-regexp'; 2 | 3 | function isUrlMatch(define, url) { 4 | return pathToRegexp(define).exec(url); 5 | } 6 | 7 | export default (url, options = {}, mockData) => { 8 | console.log(`mock for url: ${url}`); 9 | const { params, method = 'get' } = options; 10 | mockData = mockData || window.g_block_mock; 11 | const keys = Object.keys(mockData); 12 | let mockInfo = keys.find(item => { 13 | let [aMethod, aUrl] = item.split(/\s+/); 14 | if (!aUrl) { 15 | aUrl = aMethod; 16 | aMethod = '*'; 17 | } 18 | if ( 19 | (aMethod === '*' || 20 | aMethod.toLocaleLowerCase() === method.toLocaleLowerCase()) && 21 | isUrlMatch(aUrl, url) 22 | ) { 23 | return true; 24 | } 25 | return false; 26 | }); 27 | console.log(`find mock data key: ${mockInfo}`); 28 | if (mockInfo) { 29 | mockInfo = mockData[mockInfo]; 30 | let retData; 31 | if (typeof mockInfo === 'function') { 32 | retData = mockInfo( 33 | { 34 | query: params, 35 | params: {} // TODO 36 | }, 37 | {} 38 | ); 39 | } else { 40 | retData = mockInfo; 41 | } 42 | return Promise.resolve(retData); 43 | } else { 44 | throw new Error('not find mock data'); 45 | } 46 | }; 47 | -------------------------------------------------------------------------------- /src/mock-request.test.js: -------------------------------------------------------------------------------- 1 | import request from './mock-request'; 2 | 3 | describe('mock-request', () => { 4 | it('mock data right', async () => { 5 | const ret = await request( 6 | '/api/test', 7 | {}, 8 | { 9 | 'GET /api/test': 'testres' 10 | } 11 | ); 12 | expect(ret).toEqual('testres'); 13 | 14 | const ret2 = await request( 15 | '/api/test', 16 | {}, 17 | { 18 | 'GET /api/:id': 'testres2' 19 | } 20 | ); 21 | expect(ret2).toEqual('testres2'); 22 | 23 | const ret3 = await request( 24 | '/api/test', 25 | { 26 | method: 'post' 27 | }, 28 | { 29 | 'POST /api/test': () => { 30 | return 'testres-post'; 31 | }, 32 | 'GET /api/test': () => { 33 | return 'testres3'; 34 | } 35 | } 36 | ); 37 | expect(ret3).toEqual('testres-post'); 38 | 39 | const ret4 = await request( 40 | '/api/test', 41 | {}, 42 | { 43 | '/api/test': 'testres4' 44 | } 45 | ); 46 | expect(ret4).toEqual('testres4'); 47 | }); 48 | }); 49 | --------------------------------------------------------------------------------