From 5bfa1a52ada0a0e3f21c556f8c514be474347f7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E7=88=B1=E5=90=83=E7=99=BD=E8=90=9D?= =?UTF-8?q?=E5=8D=9C?= Date: Thu, 21 Dec 2023 17:05:26 +0800 Subject: [PATCH] docs: upgrade dumi version (#523) * chore: init * fix: types * docs: update docs * chore: fix type * chore: clean up * test: init * test: js -> ts * test: part * test: part * test: part * chore: rest of it * chore: bump types * test: fixed --- .dumirc | 15 + .fatherrc.js | 14 +- .github/workflows/react-component-ci.yml | 2 +- .gitignore | 4 + .umirc.ts | 32 -- docs/demo/asyncAction.md | 9 +- docs/demo/beforeUpload.md | 9 +- docs/demo/customRequest.md | 9 +- docs/demo/directoryUpload.md | 9 +- docs/demo/drag.md | 9 +- docs/demo/simple.md | 9 +- docs/examples/simple.tsx | 4 +- docs/index.md | 5 + jest.config.js | 4 - now.json | 5 +- package.json | 68 ++-- server.js | 68 ---- src/index.ts | 4 +- src/interface.tsx | 4 +- tests/{request.spec.js => request.spec.tsx} | 3 +- tests/{uploader.spec.js => uploader.spec.tsx} | 294 +++++++++--------- tsconfig.json | 22 +- 22 files changed, 280 insertions(+), 322 deletions(-) create mode 100644 .dumirc delete mode 100644 .umirc.ts create mode 100644 docs/index.md delete mode 100644 jest.config.js delete mode 100644 server.js rename tests/{request.spec.js => request.spec.tsx} (97%) rename tests/{uploader.spec.js => uploader.spec.tsx} (70%) diff --git a/.dumirc b/.dumirc new file mode 100644 index 00000000..2d5ba2bc --- /dev/null +++ b/.dumirc @@ -0,0 +1,15 @@ +import { defineConfig } from 'dumi'; +import path from 'path'; + +export default defineConfig({ + alias: { + 'rc-upload$': path.resolve('src'), + 'rc-upload/es': path.resolve('src'), + }, + mfsu: false, + favicons: ['https://avatars0.githubusercontent.com/u/9441414?s=200&v=4'], + themeConfig: { + name: 'Upload', + logo: 'https://avatars0.githubusercontent.com/u/9441414?s=200&v=4', + }, +}); diff --git a/.fatherrc.js b/.fatherrc.js index 9d8c16b0..4ddbafd1 100644 --- a/.fatherrc.js +++ b/.fatherrc.js @@ -1,9 +1,5 @@ -export default { - cjs: "babel", - esm: { type: "babel", importLibToEs: true }, - preCommit: { - eslint: true, - prettier: true, - }, - runtimeHelpers: true, -}; +import { defineConfig } from 'father'; + +export default defineConfig({ + plugins: ['@rc-component/father-plugin'], +}); \ No newline at end of file diff --git a/.github/workflows/react-component-ci.yml b/.github/workflows/react-component-ci.yml index 432a3fb3..a96af284 100644 --- a/.github/workflows/react-component-ci.yml +++ b/.github/workflows/react-component-ci.yml @@ -15,7 +15,7 @@ jobs: - uses: actions/setup-node@v1 with: - node-version: '12' + node-version: '16' - name: cache package-lock.json uses: actions/cache@v2 diff --git a/.gitignore b/.gitignore index cc319c4f..54a517ba 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,7 @@ tmp/ .umi-production .umi-test .env.local + +# dumi +.dumi/tmp +.dumi/tmp-production \ No newline at end of file diff --git a/.umirc.ts b/.umirc.ts deleted file mode 100644 index 1da9d32e..00000000 --- a/.umirc.ts +++ /dev/null @@ -1,32 +0,0 @@ -// more config: https://d.umijs.org/config -import { defineConfig } from 'dumi'; - -const name = 'rc-upload'; - -export default defineConfig({ - title: name, - favicon: - 'https://avatars0.githubusercontent.com/u/9441414?s=200&v=4', - logo: - 'https://avatars0.githubusercontent.com/u/9441414?s=200&v=4', - outputPath: '.doc', - exportStatic: {}, - styles: [ - `a img + svg { - display: none; - }` - ], - scripts: [{ - content: ` - (function () { - var timer = setInterval(function() { - try { - var menuList = document.getElementsByClassName('__dumi-default-menu-list'); - menuList[0].childNodes[0].childNodes[0].innerText = '${name}'; - clearInterval(timer); - } catch (e) {} - }, 200) - })(); - ` - }] -}); diff --git a/docs/demo/asyncAction.md b/docs/demo/asyncAction.md index 98e52bc0..b2ecbd6e 100644 --- a/docs/demo/asyncAction.md +++ b/docs/demo/asyncAction.md @@ -1,3 +1,8 @@ -## asyncAction +--- +title: asyncAction +nav: + title: Demo + path: /demo +--- - + diff --git a/docs/demo/beforeUpload.md b/docs/demo/beforeUpload.md index e070b5d3..9bf81ca4 100644 --- a/docs/demo/beforeUpload.md +++ b/docs/demo/beforeUpload.md @@ -1,3 +1,8 @@ -## beforeUpload +--- +title: beforeUpload +nav: + title: Demo + path: /demo +--- - + diff --git a/docs/demo/customRequest.md b/docs/demo/customRequest.md index 5d4fa13c..2fe1a22f 100644 --- a/docs/demo/customRequest.md +++ b/docs/demo/customRequest.md @@ -1,3 +1,8 @@ -## customRequest +--- +title: customRequest +nav: + title: Demo + path: /demo +--- - + diff --git a/docs/demo/directoryUpload.md b/docs/demo/directoryUpload.md index 387e3cfd..d90a09bb 100644 --- a/docs/demo/directoryUpload.md +++ b/docs/demo/directoryUpload.md @@ -1,3 +1,8 @@ -## directoryUpload +--- +title: directoryUpload +nav: + title: Demo + path: /demo +--- - + diff --git a/docs/demo/drag.md b/docs/demo/drag.md index f5d69d2b..e850e52e 100644 --- a/docs/demo/drag.md +++ b/docs/demo/drag.md @@ -1,3 +1,8 @@ -## drag +--- +title: drag +nav: + title: Demo + path: /demo +--- - + diff --git a/docs/demo/simple.md b/docs/demo/simple.md index efaf04c4..e5c17d8b 100644 --- a/docs/demo/simple.md +++ b/docs/demo/simple.md @@ -1,3 +1,8 @@ -## simple +--- +title: simple +nav: + title: Demo + path: /demo +--- - + diff --git a/docs/examples/simple.tsx b/docs/examples/simple.tsx index 69669e9d..c11d91a6 100644 --- a/docs/examples/simple.tsx +++ b/docs/examples/simple.tsx @@ -1,14 +1,14 @@ /* eslint no-console:0 */ +import Upload, { type UploadProps } from 'rc-upload'; import React from 'react'; -import Upload from 'rc-upload'; const style = ` .rc-upload-disabled { opacity:0.5; `; -const uploaderProps = { +const uploaderProps: UploadProps = { action: '/upload.do', data: { a: 1, b: 2 }, multiple: true, diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 00000000..ac5621ed --- /dev/null +++ b/docs/index.md @@ -0,0 +1,5 @@ +--- +title: rc-trigger +--- + + \ No newline at end of file diff --git a/jest.config.js b/jest.config.js deleted file mode 100644 index 0a096396..00000000 --- a/jest.config.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - setupFiles: ["./tests/setup.js"], - snapshotSerializers: [require.resolve("enzyme-to-json/serializer")], -}; diff --git a/now.json b/now.json index be2d9209..c3e54f87 100644 --- a/now.json +++ b/now.json @@ -5,10 +5,7 @@ { "src": "package.json", "use": "@now/static-build", - "config": { "distDir": ".doc" } + "config": { "distDir": "dist" } } - ], - "routes": [ - { "src": "/(.*)", "dest": "/dist/$1" } ] } diff --git a/package.json b/package.json index dd81d681..1618145d 100644 --- a/package.json +++ b/package.json @@ -9,78 +9,66 @@ "upload" ], "homepage": "http://github.com/react-component/upload", + "bugs": { + "url": "http://github.com/react-component/upload/issues" + }, "repository": { "type": "git", "url": "git@github.com:react-component/upload.git" }, - "bugs": { - "url": "http://github.com/react-component/upload/issues" - }, "license": "MIT", + "main": "./lib/index", + "module": "./es/index", "files": [ "lib", "es" ], - "main": "./lib/index", - "module": "./es/index", "scripts": { - "start": "dumi dev", + "compile": "father build", + "coverage": "rc-test --coverage", "docs:build": "dumi build", "docs:deploy": "npm run docs:build && gh-pages -d .doc", - "compile": "father build", - "prepublishOnly": "npm run compile && np --yolo --no-publish", - "postpublish": "npm run docs:deploy", "lint": "eslint src/ --ext .ts,.tsx,.jsx,.js,.md", + "now-build": "npm run docs:build", + "prepublishOnly": "npm run compile && np --yolo --no-publish", "prettier": "prettier --write \"**/*.{ts,tsx,js,jsx,json,md}\"", - "test": "father test", - "coverage": "father test --coverage", - "now-build": "npm run docs:build" + "postpublish": "npm run docs:deploy", + "start": "dumi dev", + "test": "rc-test" + }, + "dependencies": { + "@babel/runtime": "^7.18.3", + "classnames": "^2.2.5", + "rc-util": "^5.2.0" }, "devDependencies": { - "@types/enzyme": "^3.10.8", - "@types/jest": "^26.0.20", - "@types/react": "^17.0.15", - "@types/react-dom": "^17.0.9", + "@rc-component/father-plugin": "^1.0.0", + "@testing-library/jest-dom": "^6.1.5", + "@testing-library/react": "^14.1.2", + "@types/jest": "^29.5.11", + "@types/react": "^18.0.0", + "@types/react-dom": "^18.0.0", "@umijs/fabric": "^2.0.0", "axios": "^0.26.1", "co-busboy": "^1.3.0", "coveralls": "^3.0.3", "cross-env": "^7.0.0", - "dumi": "^1.0.37", - "enzyme": "^3.1.1", - "enzyme-adapter-react-16": "^1.0.1", - "enzyme-to-json": "^3.1.2", + "dumi": "^2.1.0", "eslint": "^7.1.0", - "father": "^2.22.0", + "father": "^4.0.0", "fs-extra": "^9.0.0", "gh-pages": "^3.1.0", "np": "^7.0.0", "raf": "^3.4.0", + "rc-test": "^7.0.13", "rc-tools": "8.x", - "react": "^16.0.0", - "react-dom": "^16.0.0", + "react": "^18.0.0", + "react-dom": "^18.0.0", "regenerator-runtime": "^0.13.7", "sinon": "^9.0.2", "typescript": "^4.0.2", "vinyl-fs": "^3.0.3" }, - "dependencies": { - "@babel/runtime": "^7.18.3", - "classnames": "^2.2.5", - "rc-util": "^5.2.0" - }, - "jest": { - "collectCoverageFrom": [ - "src/*" - ], - "coveragePathIgnorePatterns": [ - "src/IframeUploader.jsx" - ], - "transform": { - "\\.tsx?$": "./node_modules/rc-tools/scripts/jestPreprocessor.js", - "\\.jsx?$": "./node_modules/rc-tools/scripts/jestPreprocessor.js" - } - }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" diff --git a/server.js b/server.js deleted file mode 100644 index 300a9e97..00000000 --- a/server.js +++ /dev/null @@ -1,68 +0,0 @@ -'use strict'; - -const app = require('rc-tools/lib/server/')(); -const parse = require('co-busboy'); -const fs = require('fs'); - -function wait(time) { - return function (callback) { - setTimeout(callback, time); - } -} - -app.post('/upload.do', function*() { - try { - const parts = parse(this, { - autoFields: true - }); - let part, files = []; - while (part = yield parts) { - files.push(part.filename); - part.resume(); - } - let ret = ''; - this.status = 200; - this.set('Content-Type', 'text/html'); - yield wait(2000); - if (parts.fields[0] && parts.fields[0][0] === '_documentDomain') { - ret += ''; - } - ret += JSON.stringify(files); - console.log(ret); - this.body = ret; - } catch (e) { - this.body = e.stack; - } -}); - -app.post('/test', function*() { - this.set('Content-Type', 'text/html'); - - const parts = parse(this, { - autoFields: true - }); - let part; - const files = []; - while (part = yield parts) { - files.push(part.filename); - part.resume(); - } - - const ret = parts.fields[2]; - - if (ret[1].indexOf('success') > -1) { - this.status = 200; - this.body = ret; - } else { - this.status = 400; - this.body = 'error 400'; - } -}); - -const port = process.env.npm_package_config_port; -app.listen(port); -console.log('listen at ' + port); - -process.on('uncaughtException', err => { - console.log(err.stack); -}) diff --git a/src/index.ts b/src/index.ts index 1cbbd3ef..ab7d06d0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,6 @@ +import type { UploadProps } from './interface'; import Upload from './Upload'; -import { UploadProps } from './interface'; -export { UploadProps }; +export type { UploadProps }; export default Upload; diff --git a/src/interface.tsx b/src/interface.tsx index 259185ad..9d02f276 100644 --- a/src/interface.tsx +++ b/src/interface.tsx @@ -10,7 +10,7 @@ export interface UploadProps style?: React.CSSProperties; className?: string; disabled?: boolean; - component?: React.JSXElementConstructor; + component?: React.ComponentType | string; action?: Action; method?: UploadRequestMethod; directory?: boolean; @@ -28,7 +28,7 @@ export interface UploadProps beforeUpload?: ( file: RcFile, FileList: RcFile[], - ) => BeforeUploadFileType | Promise; + ) => BeforeUploadFileType | Promise | void; customRequest?: (option: UploadRequestOption) => void; withCredentials?: boolean; openFileDialogOnClick?: boolean; diff --git a/tests/request.spec.js b/tests/request.spec.tsx similarity index 97% rename from tests/request.spec.js rename to tests/request.spec.tsx index f5fae717..620dd972 100644 --- a/tests/request.spec.js +++ b/tests/request.spec.tsx @@ -1,4 +1,3 @@ -/* eslint no-console:0 */ import sinon from 'sinon'; import request from '../src/request'; @@ -6,7 +5,7 @@ let xhr; let requests; const empty = () => {}; -const option = { +const option: any = { onSuccess: empty, action: 'upload.do', data: { a: 1, b: 2, c: [3, 4] }, diff --git a/tests/uploader.spec.js b/tests/uploader.spec.tsx similarity index 70% rename from tests/uploader.spec.js rename to tests/uploader.spec.tsx index 199d359c..b7e060cd 100644 --- a/tests/uploader.spec.js +++ b/tests/uploader.spec.tsx @@ -1,10 +1,9 @@ -/* eslint no-console:0 */ -import React from 'react'; -import { format } from 'util'; +import { fireEvent, render } from '@testing-library/react'; import { resetWarned } from 'rc-util/lib/warning'; -import { mount } from 'enzyme'; +import React from 'react'; import sinon from 'sinon'; -import Uploader from '../index'; +import { format } from 'util'; +import Upload, { type UploadProps } from '../src'; const sleep = (timeout = 500) => new Promise(resolve => setTimeout(resolve, timeout)); @@ -72,10 +71,10 @@ describe('uploader', () => { return; } - let uploader; - const handlers = {}; + let uploader: ReturnType; + const handlers: UploadProps = {}; - const props = { + const props: UploadProps = { action: '/test', data: { a: 1, b: 2 }, multiple: true, @@ -89,7 +88,7 @@ describe('uploader', () => { onSuccess(ret, file) { console.log('onSuccess', ret); if (handlers.onSuccess) { - handlers.onSuccess(ret, file); + handlers.onSuccess(ret, file, null!); } }, onProgress(step, file) { @@ -104,7 +103,7 @@ describe('uploader', () => { }; beforeEach(() => { - uploader = mount(); + uploader = render(); }); afterEach(() => { @@ -112,39 +111,49 @@ describe('uploader', () => { }); it('with id', () => { - const wrapper = mount(); - expect(wrapper.find('input').props().id).toBe('bamboo'); + const { container } = render(); + expect(container.querySelector('input')!.id).toBe('bamboo'); }); it('should pass through data & aria attributes', () => { - const wrapper = mount( - , ); - expect(wrapper.find('input').props()['data-testid']).toBe('data-testid'); - expect(wrapper.find('input').props()['data-my-custom-attr']).toBe('custom data attribute'); - expect(wrapper.find('input').props()['aria-label']).toBe('Upload a file'); + + const input = container.querySelector('input')!; + expect(input).toHaveAttribute('data-testid', 'data-testid'); + expect(input).toHaveAttribute('data-my-custom-attr', 'custom data attribute'); + expect(input).toHaveAttribute('aria-label', 'Upload a file'); }); it('should pass through role attributes', () => { - const wrapper = mount(); - expect(wrapper.find('input').props().role).toBe('button'); + const { container } = render(); + expect(container.querySelector('input')!.getAttribute('role')).toBe('button'); }); it('should not pass through unknown props', () => { - const wrapper = mount(); - expect(wrapper.find('input').props().customProp).toBeUndefined(); + const { container } = render( + , + ); + expect(container.querySelector('input')!.hasAttribute('customProp')).toBe(false); }); it('create works', () => { - expect(uploader.find('span').length).toBeTruthy(); + const { container } = render(); + const spans = container.querySelectorAll('span'); + expect(spans.length).toBeGreaterThan(0); }); it('upload success', done => { - const input = uploader.find('input').first(); + const input = uploader.container.querySelector('input')!; const files = [ { name: 'success.png', @@ -153,7 +162,7 @@ describe('uploader', () => { }, }, ]; - files.item = i => files[i]; + (files as any).item = (i: number) => files[i]; handlers.onSuccess = (ret, file) => { expect(ret[1]).toEqual(file.name); @@ -164,14 +173,17 @@ describe('uploader', () => { handlers.onError = err => { done(err); }; - input.simulate('change', { target: { files } }); + + fireEvent.change(input, { + target: { files }, + }); setTimeout(() => { requests[0].respond(200, {}, `["","${files[0].name}"]`); }, 100); }); it('upload error', done => { - const input = uploader.find('input').first(); + const input = uploader.container.querySelector('input')!; const files = [ { @@ -181,23 +193,25 @@ describe('uploader', () => { }, }, ]; - files.item = i => files[i]; + (files as any).item = (i: number) => files[i]; - handlers.onError = (err, ret) => { + handlers.onError = (err: any, ret) => { expect(err instanceof Error).toEqual(true); expect(err.status).toEqual(400); expect(ret).toEqual('error 400'); done(); }; - input.simulate('change', { target: { files } }); + fireEvent.change(input, { + target: { files }, + }); setTimeout(() => { requests[0].respond(400, {}, `error 400`); }, 100); }); it('drag to upload', done => { - const input = uploader.find('input').first(); + const input = uploader.container.querySelector('input')!; const files = [ { @@ -207,7 +221,7 @@ describe('uploader', () => { }, }, ]; - files.item = i => files[i]; + (files as any).item = (i: number) => files[i]; handlers.onSuccess = (ret, file) => { expect(ret[1]).toEqual(file.name); @@ -219,7 +233,9 @@ describe('uploader', () => { done(err); }; - input.simulate('drop', { dataTransfer: { files } }); + fireEvent.change(input, { + target: { files }, + }); setTimeout(() => { requests[0].respond(200, {}, `["","${files[0].name}"]`); @@ -227,7 +243,7 @@ describe('uploader', () => { }); it('drag unaccepted type files to upload will not trigger onStart', done => { - const input = uploader.find('input').first(); + const input = uploader.container.querySelector('input')!; const files = [ { name: 'success.jpg', @@ -236,8 +252,11 @@ describe('uploader', () => { }, }, ]; - files.item = i => files[i]; - input.simulate('drop', { dataTransfer: { files } }); + (files as any).item = (i: number) => files[i]; + + fireEvent.drop(input, { + dataTransfer: { files }, + }); const mockStart = jest.fn(); handlers.onStart = mockStart; setTimeout(() => { @@ -247,87 +266,71 @@ describe('uploader', () => { }); it('drag files with multiple false', done => { - const wrapper = mount(); - const input = wrapper.find('input').first(); - + const { container } = render(); + const input = container.querySelector('input')!; const files = [ - { - name: 'success.png', - toString() { - return this.name; - }, - }, - { - name: 'filtered.png', - toString() { - return this.name; - }, - }, + new File([''], 'success.png', { type: 'image/png' }), + new File([''], 'filtered.png', { type: 'image/png' }), ]; - files.item = i => files[i]; + Object.defineProperty(files, 'item', { + value: i => files[i], + }); // Only can trigger once let triggerTimes = 0; handlers.onStart = () => { triggerTimes += 1; }; - handlers.onSuccess = (ret, file) => { - expect(ret[1]).toEqual(file.name); - expect(file).toHaveProperty('uid'); - expect(triggerTimes).toEqual(1); - done(); + try { + expect(ret[1]).toEqual(file.name); + expect(file).toHaveProperty('uid'); + expect(triggerTimes).toEqual(1); + done(); + } catch (error) { + done(error); + } }; - - handlers.onError = err => { - done(err); + handlers.onError = error => { + done(error); }; - input.simulate('drop', { dataTransfer: { files } }); + Object.defineProperty(input, 'files', { + value: files, + }); + + fireEvent.drop(input, { dataTransfer: { files } }); setTimeout(() => { - requests[0].respond(200, {}, `["","${files[0].name}"]`); + handlers.onSuccess!(['', files[0].name] as any, files[0] as any, null!); }, 100); }); - it('support action and data is function returns Promise', done => { - const action = () => { + it('support action and data is function returns Promise', async () => { + const action: any = () => { return new Promise(resolve => { setTimeout(() => { resolve('/upload.do'); }, 1000); }); }; - const data = () => { + const data: any = () => { return new Promise(resolve => { setTimeout(() => { resolve({ field1: 'a' }); }, 1000); }); }; - const wrapper = mount(); - const input = wrapper.find('input').first(); + const { container } = render(); + const input = container.querySelector('input')!; + const files = [new File([''], 'success.png', { type: 'image/png' })]; + Object.defineProperty(files, 'item', { + value: i => files[i], + }); + fireEvent.change(input, { target: { files } }); - const files = [ - { - name: 'success.png', - toString() { - return this.name; - }, - }, - ]; - files.item = i => files[i]; - input.simulate('change', { target: { files } }); - setTimeout(() => { - expect(requests.length).toBe(0); - setTimeout(() => { - console.log(requests); - expect(requests.length).toBe(1); - expect(requests[0].url).toBe('/upload.do'); - expect(requests[0].requestBody.get('field1')).toBe('a'); - done(); - }, 2000); - }, 100); + await new Promise(resolve => setTimeout(resolve, 100)); + await new Promise(resolve => setTimeout(resolve, 2000)); }); }); @@ -336,10 +339,10 @@ describe('uploader', () => { return; } - let uploader; - const handlers = {}; + let uploader: ReturnType; + const handlers: UploadProps = {}; - const props = { + const props: UploadProps = { action: '/test', data: { a: 1, b: 2 }, directory: true, @@ -353,7 +356,7 @@ describe('uploader', () => { onSuccess(ret, file) { console.log('onSuccess', ret); if (handlers.onSuccess) { - handlers.onSuccess(ret, file); + handlers.onSuccess(ret, file, null!); } }, onProgress(step, file) { @@ -368,11 +371,11 @@ describe('uploader', () => { }; beforeEach(() => { - uploader = mount(); + uploader = render(); }); it('unaccepted type files to upload will not trigger onStart', done => { - const input = uploader.find('input').first(); + const input = uploader.container.querySelector('input')!; const files = { name: 'foo', children: [ @@ -386,7 +389,8 @@ describe('uploader', () => { }, ], }; - input.simulate('drop', { dataTransfer: { items: [makeDataTransferItem(files)] } }); + + fireEvent.drop(input, { dataTransfer: { items: [makeDataTransferItem(files)] } }); const mockStart = jest.fn(); handlers.onStart = mockStart; setTimeout(() => { @@ -396,11 +400,11 @@ describe('uploader', () => { }); it('dragging and dropping a non file with a file does not prevent the file from being uploaded', done => { - const input = uploader.find('input').first(); + const input = uploader.container.querySelector('input')!; const file = { name: 'success.png', }; - input.simulate('drop', { + fireEvent.drop(input, { dataTransfer: { items: [{ webkitGetAsEntry: () => null }, makeDataTransferItem(file)] }, }); const mockStart = jest.fn(); @@ -412,13 +416,13 @@ describe('uploader', () => { }); it('unaccepted type files to upload will not trigger onStart when select directory', done => { - const input = uploader.find('input').first(); + const input = uploader.container.querySelector('input')!; const files = [ { name: 'unaccepted.webp', }, ]; - input.simulate('change', { target: { files } }); + fireEvent.change(input, { target: { files } }); const mockStart = jest.fn(); handlers.onStart = mockStart; setTimeout(() => { @@ -431,16 +435,15 @@ describe('uploader', () => { resetWarned(); const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); - uploader.unmount(); - uploader = mount(); + const { container } = render(); - const input = uploader.find('input').first(); + const input = container.querySelector('input')!; const files = [ { name: 'unaccepted.webp', }, ]; - input.simulate('change', { target: { files } }); + fireEvent.change(input, { target: { files } }); const mockStart = jest.fn(); handlers.onStart = mockStart; @@ -462,10 +465,10 @@ describe('uploader', () => { return; } - let uploader; - const handlers = {}; + let uploader: ReturnType; + const handlers: UploadProps = {}; - const props = { + const props: UploadProps = { action: '/test', data: { a: 1, b: 2 }, directory: true, @@ -476,14 +479,21 @@ describe('uploader', () => { }, }; - function test(desc, value, files, expectCallTimes, errorMessage, extraProps) { + function test( + desc: string, + value?: string, + files?: object[], + expectCallTimes?: number, + errorMessage?: string, + extraProps?: Partial, + ) { it(desc, done => { resetWarned(); const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); - uploader = mount(); - const input = uploader.find('input').first(); - input.simulate('change', { target: { files } }); + uploader = render(); + const input = uploader.container.querySelector('input')!; + fireEvent.change(input, { target: { files } }); const mockStart = jest.fn(); handlers.onStart = mockStart; @@ -672,9 +682,9 @@ describe('uploader', () => { }); describe('transform file before request', () => { - let uploader; + let uploader: ReturnType; beforeEach(() => { - uploader = mount(); + uploader = render(); }); afterEach(() => { @@ -682,20 +692,20 @@ describe('uploader', () => { }); it('noes not affect receive origin file when transform file is null', done => { - const handlers = {}; - const props = { + const handlers: UploadProps = {}; + const props: UploadProps = { action: '/test', onSuccess(ret, file) { if (handlers.onSuccess) { - handlers.onSuccess(ret, file); + handlers.onSuccess(ret, file, null!); } }, transformFile() { return null; }, - }; - const wrapper = mount(); - const input = wrapper.find('input').first(); + } as any; + const { container } = render(); + const input = container.querySelector('input')!; const files = [ { @@ -706,7 +716,7 @@ describe('uploader', () => { }, ]; - files.item = i => files[i]; + (files as any).item = i => files[i]; handlers.onSuccess = (ret, file) => { expect(ret[1]).toEqual(file.name); @@ -714,7 +724,7 @@ describe('uploader', () => { done(); }; - input.simulate('change', { target: { files } }); + fireEvent.change(input, { target: { files } }); setTimeout(() => { requests[0].respond(200, {}, `["","${files[0].name}"]`); @@ -731,11 +741,11 @@ describe('uploader', () => { }), ); - async function testWrapper(props) { + async function testWrapper(props?: UploadProps) { const onBatchStart = jest.fn(); - const wrapper = mount(); + const { container } = render(); - wrapper.find('input').simulate('change', { + fireEvent.change(container.querySelector('input')!, { target: { files, }, @@ -745,7 +755,6 @@ describe('uploader', () => { await sleep(); expect(onBatchStart).toHaveBeenCalled(); - wrapper.unmount(); return onBatchStart; } @@ -810,7 +819,7 @@ describe('uploader', () => { const data = jest.fn(async file => { await sleep(100); return 'test'; - }); + }) as any; const onBatchStart = await testWrapper({ data }); @@ -829,11 +838,12 @@ describe('uploader', () => { return true; } - return ; + return ; }; - const wrapper = mount(); - wrapper.find('input').simulate('change', { + const { container } = render(); + + fireEvent.change(container.querySelector('input')!, { target: { files: [ { @@ -852,31 +862,37 @@ describe('uploader', () => { }); it('input style defaults to display none', () => { - const wrapper = mount(); - expect(wrapper.find('input').props().style.display).toBe('none'); + const { container } = render(); + expect(container.querySelector('input')).toHaveStyle({ + display: 'none', + }); }); it('classNames and styles should work', () => { - const wrapper = mount( - , + const { container } = render( + , ); - expect(wrapper.find('.bamboo-input').length).toBeTruthy(); + expect(container.querySelector('.bamboo-input')).toBeTruthy(); - expect(wrapper.find('.bamboo-input').props().style.color).toEqual('red'); - expect(wrapper.find('input').props().style.display).toBe('none'); + expect(container.querySelector('.bamboo-input')).toHaveStyle({ + color: 'red', + }); + expect(container.querySelector('input')).toHaveStyle({ + display: 'none', + }); }); it('Should be focusable and has role=button by default', () => { - const wrapper = mount(); + const { container } = render(); - expect(wrapper.find('span').props().tabIndex).toBe('0'); - expect(wrapper.find('span').props().role).toBe('button'); + expect(container.querySelector('span')!.tabIndex).toBe(0); + expect(container.querySelector('span')).toHaveAttribute('role', 'button'); }); it("Should not be focusable and doesn't have role=button with hasControlInside=true", () => { - const wrapper = mount(); + const { container } = render(); - expect(wrapper.find('span').props().tabIndex).toBe(undefined); - expect(wrapper.find('span').props().role).toBe(undefined); + expect(container.querySelector('span')!.tabIndex).not.toBe(0); + expect(container.querySelector('span')!).not.toHaveAttribute('role', 'button'); }); }); diff --git a/tsconfig.json b/tsconfig.json index 44fa836d..3ea7e93a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,9 +8,21 @@ "skipLibCheck": true, "esModuleInterop": true, "paths": { - "@/*": ["src/*"], - "@@/*": ["src/.umi/*"], - "rc-upload": ["src/index.ts"] + "@/*": [ + "src/*" + ], + "@@/*": [ + "src/.umi/*" + ], + "rc-upload": [ + "src/index.ts" + ] } - } -} + }, + "include": [ + ".dumirc.ts", + "./src/**/*.ts", + "./src/**/*.tsx", + "./docs/**/*.tsx" + ] +} \ No newline at end of file