From 0aa89aaec46ab38d05ad5389ef74553953040988 Mon Sep 17 00:00:00 2001 From: CodingOnStar <447357187@qq.com> Date: Fri, 19 Aug 2022 10:32:19 +0800 Subject: [PATCH 1/6] =?UTF-8?q?fix(tab):=20=E4=BD=BF=E7=94=A8=E5=8E=9F?= =?UTF-8?q?=E7=94=9F=E5=B1=9E=E6=80=A7=E6=9B=BF=E6=8D=A2=E8=B6=85=E9=95=BF?= =?UTF-8?q?=E6=BB=9A=E5=8A=A8=E7=9A=84offset?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #781 --- src/tabs/tabs.ts | 45 +++++++++++++++++++++++---------------------- src/tabs/tabs.wxml | 2 ++ 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/src/tabs/tabs.ts b/src/tabs/tabs.ts index f6c805542..9993f4543 100644 --- a/src/tabs/tabs.ts +++ b/src/tabs/tabs.ts @@ -69,7 +69,8 @@ export default class Tabs extends SuperComponent { isScrollY: false, direction: 'X', animate: { duration: 0 }, - offset: 0, + // offset: 0, + itemId: 'item0', }; created() { @@ -140,19 +141,19 @@ export default class Tabs extends SuperComponent { } } - calcScrollOffset( - containerWidth: number, - totalWidth: number, - targetLeft: number, - targetWidth: number, - offset: number, - ) { - if (offset + targetLeft > containerWidth / 2) { - const maxOffset = totalWidth - containerWidth; - return Math.min(Math.abs(containerWidth / 2 - targetLeft - offset - targetWidth / 2), maxOffset); - } - return 0; - } + // calcScrollOffset( + // containerWidth: number, + // totalWidth: number, + // targetLeft: number, + // targetWidth: number, + // offset: number, + // ) { + // if (offset + targetLeft > containerWidth / 2) { + // const maxOffset = totalWidth - containerWidth; + // return Math.min(Math.abs(containerWidth / 2 - targetLeft - offset - targetWidth / 2), maxOffset); + // } + // return 0; + // } setTrack() { if (!this.properties.showBottomLine) return; @@ -175,15 +176,15 @@ export default class Tabs extends SuperComponent { } if (this.containerWidth) { - const offset = this.calcScrollOffset( - this.containerWidth, - rect.width * res.length, - rect.left, - rect.width, - this.data.offset, - ); + // const offset = this.calcScrollOffset( + // this.containerWidth, + // rect.width * res.length, + // rect.left, + // rect.width, + // this.data.offset, + // ); this.setData({ - offset, + itemId: `item${rect.dataset.index}`, }); } diff --git a/src/tabs/tabs.wxml b/src/tabs/tabs.wxml index e1ee52593..4b5fdf660 100644 --- a/src/tabs/tabs.wxml +++ b/src/tabs/tabs.wxml @@ -16,12 +16,14 @@ scroll-x="{{isScrollX}}" scroll-y="{{isScrollY}}" scroll-with-animation + scroll-into-view="{{itemId}}" > From 4d244f21be9d49dfbdaf263a4861e383e96d6f17 Mon Sep 17 00:00:00 2001 From: CodingOnStar <447357187@qq.com> Date: Mon, 22 Aug 2022 10:47:14 +0800 Subject: [PATCH 2/6] =?UTF-8?q?fix:=20=E5=8E=BB=E9=99=A4=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E4=B8=AD=E7=9A=84=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #781 --- src/tabs/tabs.ts | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/src/tabs/tabs.ts b/src/tabs/tabs.ts index 9993f4543..698c73d60 100644 --- a/src/tabs/tabs.ts +++ b/src/tabs/tabs.ts @@ -69,7 +69,6 @@ export default class Tabs extends SuperComponent { isScrollY: false, direction: 'X', animate: { duration: 0 }, - // offset: 0, itemId: 'item0', }; @@ -141,20 +140,6 @@ export default class Tabs extends SuperComponent { } } - // calcScrollOffset( - // containerWidth: number, - // totalWidth: number, - // targetLeft: number, - // targetWidth: number, - // offset: number, - // ) { - // if (offset + targetLeft > containerWidth / 2) { - // const maxOffset = totalWidth - containerWidth; - // return Math.min(Math.abs(containerWidth / 2 - targetLeft - offset - targetWidth / 2), maxOffset); - // } - // return 0; - // } - setTrack() { if (!this.properties.showBottomLine) return; const { children } = this; @@ -176,13 +161,6 @@ export default class Tabs extends SuperComponent { } if (this.containerWidth) { - // const offset = this.calcScrollOffset( - // this.containerWidth, - // rect.width * res.length, - // rect.left, - // rect.width, - // this.data.offset, - // ); this.setData({ itemId: `item${rect.dataset.index}`, }); From 436850e589513d489dc25c1d656863dbdc9a568c Mon Sep 17 00:00:00 2001 From: CodingOnStar <447357187@qq.com> Date: Mon, 29 Aug 2022 10:13:16 +0800 Subject: [PATCH 3/6] feat: merge --- CHANGELOG.md | 18 + package.json | 3 +- script/coverage-badge.js | 11 +- src/badge/__test__/index.test.js | 18 +- src/divider/__test__/index.test.js | 10 +- src/drawer/__test__/index.test.js | 2 +- src/empty/README.md | 1 + src/empty/__test__/index.test.js | 55 +++ src/footer/README.md | 1 + .../__test__/__snapshots__/index.test.js.snap | 17 + src/footer/__test__/index.test.js | 21 ++ src/image-viewer/_example/base/index.js | 9 +- src/image-viewer/image-viewer.less | 6 +- src/image-viewer/image-viewer.ts | 44 +-- src/image-viewer/image-viewer.wxml | 4 +- src/popup/README.md | 2 +- src/popup/popup.wxml | 4 +- src/popup/props.ts | 1 + src/search/README.md | 1 + src/search/__test__/index.test.js | 329 ++++++++++++++++++ src/steps/__test__/index.js | 38 ++ src/steps/__test__/index.json | 6 + src/steps/__test__/index.test.js | 127 +++++++ src/steps/__test__/index.wxml | 38 ++ src/switch/README.md | 1 + .../__test__/__snapshots__/index.test.js.snap | 22 ++ src/switch/__test__/index.test.js | 226 ++++++++++++ src/switch/props.ts | 8 +- src/switch/type.ts | 8 +- src/tab-bar/_example/custom/index.wxss | 10 +- src/toast/README.en-US.md | 25 ++ src/toast/README.md | 9 +- src/toast/__test__/index.test.js | 44 +++ src/toast/index.ts | 1 + src/toast/toast.ts | 3 + src/toast/type.ts | 2 +- test/utils/colors.js | 4 +- 37 files changed, 1051 insertions(+), 78 deletions(-) create mode 100644 src/empty/__test__/index.test.js create mode 100644 src/footer/__test__/__snapshots__/index.test.js.snap create mode 100644 src/footer/__test__/index.test.js create mode 100644 src/search/__test__/index.test.js create mode 100644 src/steps/__test__/index.js create mode 100644 src/steps/__test__/index.json create mode 100644 src/steps/__test__/index.test.js create mode 100644 src/steps/__test__/index.wxml create mode 100644 src/switch/__test__/__snapshots__/index.test.js.snap create mode 100644 src/switch/__test__/index.test.js create mode 100644 src/toast/README.en-US.md create mode 100644 src/toast/__test__/index.test.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c53f3b60..832326fe6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,24 @@ toc: false docClass: timeline --- +## 🌈 0.19.2 `2022-08-22` +### 🚀 Features +- `Badge`: 新增单元测试 @Perisiguiendo ([#776](https://github.com/Tencent/tdesign-miniprogram/pull/776)) +- `Input`: 新增单元测试 @anlyyao ([#775](https://github.com/Tencent/tdesign-miniprogram/pull/775)) +- `Textarea`: 新增单元测试 @anlyyao ([#774](https://github.com/Tencent/tdesign-miniprogram/pull/774)) +- `Stepper`: 新增单元测试 @anlyyao ([#773](https://github.com/Tencent/tdesign-miniprogram/pull/773)) +- `Divider`: 新增单元测试 @Perisiguiendo ([#771](https://github.com/Tencent/tdesign-miniprogram/pull/771)) +- `Result`: 新增单元测试 @CodingOnStar ([#769](https://github.com/Tencent/tdesign-miniprogram/pull/769)) +- `Progress`: `strokeWidth` 支持字符类型 @anlyyao ([#772](https://github.com/Tencent/tdesign-miniprogram/pull/772)) +- `Progress`: 更新测试用例 @anlyyao ([#772](https://github.com/Tencent/tdesign-miniprogram/pull/772)) +- `Rate`: 新增单元测试 @isanxia ([#767](https://github.com/Tencent/tdesign-miniprogram/pull/767)) +- `ImageViewer`: 更新 `demo` 示例图片 @anlyyao ([#782](https://github.com/Tencent/tdesign-miniprogram/pull/782)) +- `Rate`: 新增单元测试 @isanxia ([#767](https://github.com/Tencent/tdesign-miniprogram/pull/767)) +### 🐞 Bug Fixes +- `Badge`: 修复 `showZero` && `offset` 无单位情况 @Perisiguiendo ([#776](https://github.com/Tencent/tdesign-miniprogram/pull/776)) +- `Popup`: 修复 `zIndex` 无效问题 @anlyyao ([#784](https://github.com/Tencent/tdesign-miniprogram/pull/784)) +- `ImageViewer`: 修复图片宽高都小于屏幕宽高时的拉伸问题 @anlyyao ([#782](https://github.com/Tencent/tdesign-miniprogram/pull/782)) + ## 🌈 0.19.1 `2022-08-15` ### 🚀 Features - `Upload`: 新增 click 事件 @LeeJim ([#762](https://github.com/Tencent/tdesign-miniprogram/pull/762)) diff --git a/package.json b/package.json index ea1415fbc..eff3ae48a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "tdesign-miniprogram", "purename": "tdesign", - "version": "0.19.1", + "version": "0.19.2", "description": "tdesign-miniprogram", "title": "tdesign-miniprogram", "main": "miniprogram_dist/index.js", @@ -32,6 +32,7 @@ "site:prerender": "node script/prerender.mjs", "cover": "jest --coverage", "test": "jest && jest -c jest.e2e.config.js", + "test:demo": "node gen-demo-test.js", "test:unit": "jest", "test:e2e": "jest -c jest.e2e.config.js", "badge": "node script/coverage-badge.js", diff --git a/script/coverage-badge.js b/script/coverage-badge.js index a251f0194..ad13d67b1 100644 --- a/script/coverage-badge.js +++ b/script/coverage-badge.js @@ -1,5 +1,6 @@ const path = require('path'); const fs = require('fs'); +const os = require('os'); const specify = process.argv[2]; @@ -8,8 +9,9 @@ const data = require('../test/unit/coverage/coverage-summary.json'); const ans = new Map(); Object.keys(data).forEach((fPath) => { - if (fPath.startsWith('/')) { - const [, component] = /src\/([\w-]+)\//.exec(fPath) ?? []; + const _fPath = os.platform() === 'win32' ? fPath.slice(2).replace(/\\/g, '/') : fPath; + if (_fPath.startsWith('/')) { + const [, component] = /src\/([\w-]+)\//.exec(_fPath) ?? []; if (component) { if (!fPath.includes('/_example/')) { @@ -35,7 +37,7 @@ Object.keys(data).forEach((fPath) => { ans.forEach((items, component) => { let svgs = ''; Object.entries(items).forEach(([type, item]) => { - let val = ((item.covered / item.total) * 100).toFixed(0); + let val = item.total === 0 ? 100 : ((item.covered / item.total) * 100).toFixed(0); const relatedMap = { avatar: 'avatar-group', button: 'button-group', @@ -55,7 +57,8 @@ ans.forEach((items, component) => { if (component in relatedMap) { const related = ans.get(relatedMap[component]); if (related) { - val = (((item.covered + related[type].covered) / (item.total + related[type].total)) * 100).toFixed(0); + const denominator = item.total + related[type].total; + val = denominator === 0 ? 100 : (((item.covered + related[type].covered) / denominator) * 100).toFixed(0); } } const message = isNaN(val) ? '0' : val; diff --git a/src/badge/__test__/index.test.js b/src/badge/__test__/index.test.js index a06aef43f..3acb2e143 100644 --- a/src/badge/__test__/index.test.js +++ b/src/badge/__test__/index.test.js @@ -28,7 +28,7 @@ describe('badge', () => { it(':color', () => { const id = simulate.load({ - template: ``, + template: ``, usingComponents: { 't-badge': badge, }, @@ -45,7 +45,7 @@ describe('badge', () => { it(':content', () => { const id = simulate.load({ - template: ``, + template: ``, usingComponents: { 't-badge': badge, }, @@ -62,7 +62,7 @@ describe('badge', () => { it(':count', () => { const id = simulate.load({ - template: ``, + template: ``, usingComponents: { 't-badge': badge, }, @@ -79,7 +79,7 @@ describe('badge', () => { it(':max-count', () => { const id = simulate.load({ - template: ``, + template: ``, usingComponents: { 't-badge': badge, }, @@ -98,7 +98,7 @@ describe('badge', () => { shapes.forEach((shape) => { it(`:shape ${shape}`, () => { const id = simulate.load({ - template: ``, + template: ``, usingComponents: { 't-badge': badge, }, @@ -118,7 +118,7 @@ describe('badge', () => { sizes.forEach((size) => { it(`:size ${size}`, () => { const id = simulate.load({ - template: ``, + template: ``, usingComponents: { 't-badge': badge, }, @@ -140,7 +140,7 @@ describe('badge', () => { it(':show-zero', async () => { const id = simulate.load({ - template: ``, + template: ``, usingComponents: { 't-badge': badge, }, @@ -164,7 +164,7 @@ describe('badge', () => { it(':offset string with unit', async () => { const id = simulate.load({ - template: ``, + template: ``, usingComponents: { 't-badge': badge, }, @@ -184,7 +184,7 @@ describe('badge', () => { it(':offset number without unit', async () => { const id = simulate.load({ - template: ``, + template: ``, usingComponents: { 't-badge': badge, }, diff --git a/src/divider/__test__/index.test.js b/src/divider/__test__/index.test.js index 10e82a41c..86fce3291 100644 --- a/src/divider/__test__/index.test.js +++ b/src/divider/__test__/index.test.js @@ -16,7 +16,7 @@ describe('Divider', () => { textAlign.forEach((align) => { it(`:align ${align} render correctly`, () => { const id = simulate.load({ - template: ``, + template: ``, usingComponents: { 't-divider': divider, }, @@ -34,7 +34,7 @@ describe('Divider', () => { it(`:content string render correctly`, () => { const id = simulate.load({ - template: ``, + template: ``, usingComponents: { 't-divider': divider, }, @@ -65,7 +65,7 @@ describe('Divider', () => { it(':dashed render correctly', () => { const id = simulate.load({ - template: ``, + template: ``, usingComponents: { 't-divider': divider, }, @@ -83,7 +83,7 @@ describe('Divider', () => { layout.forEach((lay) => { it(`:layout ${lay} render correctly`, () => { const id = simulate.load({ - template: ``, + template: ``, data: { layout: 'horizontal', }, @@ -102,7 +102,7 @@ describe('Divider', () => { it(':line-color render correctly', () => { const lineColor = '#eee'; const id = simulate.load({ - template: ``, + template: ``, usingComponents: { 't-divider': divider, }, diff --git a/src/drawer/__test__/index.test.js b/src/drawer/__test__/index.test.js index 33543213c..1ab87293d 100644 --- a/src/drawer/__test__/index.test.js +++ b/src/drawer/__test__/index.test.js @@ -72,7 +72,7 @@ describe('drawer', () => { const comp = simulate.render(id); comp.attach(document.createElement('parent-wrapper')); - const popup = comp.querySelector('.base >>> .t-popup__content'); + const popup = comp.querySelector('.base >>> .t-popup'); expect(popup.dom.getAttribute('style').includes('z-index:99')).toBeTruthy(); }); }); diff --git a/src/empty/README.md b/src/empty/README.md index 0059071ea..3a5f7592a 100644 --- a/src/empty/README.md +++ b/src/empty/README.md @@ -5,6 +5,7 @@ spline: data isComponent: true --- + ## 引入 全局引入,在 miniprogram 根目录下的`app.json`中配置,局部引入,在需要引入的页面或组件的`index.json`中配置。 diff --git a/src/empty/__test__/index.test.js b/src/empty/__test__/index.test.js new file mode 100644 index 000000000..6bac2af2c --- /dev/null +++ b/src/empty/__test__/index.test.js @@ -0,0 +1,55 @@ +import simulate from 'miniprogram-simulate'; +import path from 'path'; + +describe('empty', () => { + const empty = simulate.load(path.resolve(__dirname, `../empty`), { + less: true, + }); + + describe('props', () => { + it(`:image`, () => { + const id = simulate.load({ + template: ``, + data: { + description: '描述文字', + image: 'https://oteam-tdesign-1258344706.cos.ap-guangzhou.myqcloud.com/miniprogram/empty__demo-image.png', + }, + methods: {}, + usingComponents: { + 't-empty': empty, + }, + }); + + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const image = comp.querySelector('.base >>> .t-class-image'); + expect(image).not.toBeUndefined(); + }); + + it(`:action`, async () => { + const goEmptyPage = jest.fn(); + const id = simulate.load({ + template: ` + 空页面 + `, + methods: { + goEmptyPage, + }, + usingComponents: { + 't-empty': empty, + }, + }); + + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const slotAction = comp.querySelector('.base >>> .slotAction'); + expect(slotAction).not.toBeUndefined(); + + slotAction.dispatchEvent('tap'); + await simulate.sleep(5); + expect(goEmptyPage).toHaveBeenCalledTimes(1); + }); + }); +}); diff --git a/src/footer/README.md b/src/footer/README.md index 7b1c91231..42c7001e8 100644 --- a/src/footer/README.md +++ b/src/footer/README.md @@ -5,6 +5,7 @@ spline: data isComponent: true --- + ## 引入 全局引入,在 miniprogram 根目录下的`app.json`中配置,局部引入,在需要引入的页面或组件的`index.json`中配置。 diff --git a/src/footer/__test__/__snapshots__/index.test.js.snap b/src/footer/__test__/__snapshots__/index.test.js.snap new file mode 100644 index 000000000..d43294ff8 --- /dev/null +++ b/src/footer/__test__/__snapshots__/index.test.js.snap @@ -0,0 +1,17 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Footer :base 1`] = ` +
+
+ + + + + +
+
+`; diff --git a/src/footer/__test__/index.test.js b/src/footer/__test__/index.test.js new file mode 100644 index 000000000..e53d19b73 --- /dev/null +++ b/src/footer/__test__/index.test.js @@ -0,0 +1,21 @@ +import simulate from 'miniprogram-simulate'; +import path from 'path'; + +describe('Footer', () => { + const footer = simulate.load(path.resolve(__dirname, `../footer`), { + less: true, + }); + + it(':base', () => { + const id = simulate.load({ + template: ``, + usingComponents: { + 't-footer': footer, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + expect(comp.toJSON()).toMatchSnapshot(); + }); +}); diff --git a/src/image-viewer/_example/base/index.js b/src/image-viewer/_example/base/index.js index 255cd1793..b859161d4 100644 --- a/src/image-viewer/_example/base/index.js +++ b/src/image-viewer/_example/base/index.js @@ -12,9 +12,12 @@ Component({ clickHandle() { this.setData({ images: [ - ...Array.from({ length: 6 }).fill( - 'https://oteam-tdesign-1258344706.cos.ap-guangzhou.myqcloud.com/miniprogram/images/preview1.png', - ), + 'https://oteam-tdesign-1258344706.cos-internal.ap-guangzhou.tencentcos.cn/site/miniprogram-doc/doc-steps.png', + 'https://oteam-tdesign-1258344706.cos-internal.ap-guangzhou.tencentcos.cn/site/miniprogram-doc/demo/image-viewer/demo-image.png', + 'https://oteam-tdesign-1258344706.cos.ap-guangzhou.myqcloud.com/miniprogram/images/preview1.png', + 'https://oteam-tdesign-1258344706.cos.ap-guangzhou.myqcloud.com/miniprogram/images/preview2.png', + 'https://oteam-tdesign-1258344706.cos.ap-guangzhou.myqcloud.com/miniprogram/images/preview3.png', + 'https://oteam-tdesign-1258344706.cos.ap-guangzhou.myqcloud.com/miniprogram/images/preview4.png', ], showIndex: true, visible: true, diff --git a/src/image-viewer/image-viewer.less b/src/image-viewer/image-viewer.less index 7b48f5064..723a02bed 100644 --- a/src/image-viewer/image-viewer.less +++ b/src/image-viewer/image-viewer.less @@ -41,9 +41,9 @@ transform: translateY(-50%); } - .t-class-image { - width: inherit !important; - height: inherit !important; + .t-image--external { + width: inherit; + height: inherit; display: block; } diff --git a/src/image-viewer/image-viewer.ts b/src/image-viewer/image-viewer.ts index 79ce39b5e..8f0b2452d 100644 --- a/src/image-viewer/image-viewer.ts +++ b/src/image-viewer/image-viewer.ts @@ -57,51 +57,35 @@ export default class ImageViewer extends SuperComponent { calcImageDisplayStyle(imageWidth, imageHeight) { const { windowWidth, windowHeight } = this.data; + const ratio = imageWidth / imageHeight; // 图片宽高都小于屏幕宽高 if (imageWidth < windowWidth && imageHeight < windowHeight) { return { - mode: 'scaleToFill', styleObj: { - width: '100%', + width: `${imageWidth * 2}rpx`, height: `${imageHeight * 2}rpx`, - }, - }; - } - - // 图片宽高都大等于屏幕宽高 - if (imageWidth >= windowWidth && imageHeight >= windowHeight) { - return { - mode: 'aspectFit', - styleObj: { - width: '100%', - height: `${(imageHeight / (imageWidth / windowWidth)) * 2}rpx`, - }, - }; - } - - // 图片超高:图片宽小于屏幕宽,图片高大于等于屏幕高 - if (imageWidth < windowWidth && imageHeight >= windowHeight) { - return { - mode: 'widthFix', - styleObj: { - width: `${(imageWidth / (imageHeight / windowHeight)) * 2}rpx`, - height: '100vh', left: '50%', transform: 'translate(-50%, -50%)', }, }; } - - // 图片超宽:图片宽大于等于屏幕宽,图片高小于屏幕高 - if (imageWidth >= windowWidth && imageHeight < windowHeight) { + // 图片宽高至少存在一个大于屏幕宽高,此时判断图片宽高比,按长边显示 + if (ratio >= 1) { return { - mode: 'heightFix', styleObj: { - width: '100%', - height: `${(imageHeight / (imageWidth / windowWidth)) * 2}rpx`, + width: '100vw', + height: `${(windowWidth / ratio) * 2}rpx`, }, }; } + return { + styleObj: { + width: `${ratio * windowHeight * 2}rpx`, + height: '100vh', + left: '50%', + transform: 'translate(-50%, -50%)', + }, + }; }, onImageLoadSuccess(e: WechatMiniprogram.TouchEvent) { diff --git a/src/image-viewer/image-viewer.wxml b/src/image-viewer/image-viewer.wxml index f5ac534f9..37823d19c 100644 --- a/src/image-viewer/image-viewer.wxml +++ b/src/image-viewer/image-viewer.wxml @@ -17,9 +17,9 @@ bind:tap="onClose" > - + diff --git a/src/popup/props.ts b/src/popup/props.ts index 478a08056..957c390ba 100644 --- a/src/popup/props.ts +++ b/src/popup/props.ts @@ -60,6 +60,7 @@ const props: TdPopupProps = { /** 组件层级,Web 侧样式默认为 5500,移动端和小程序样式默认为 1500 */ zIndex: { type: Number, + value: 11500, }, }; diff --git a/src/search/README.md b/src/search/README.md index b69148f8a..235c813ee 100644 --- a/src/search/README.md +++ b/src/search/README.md @@ -5,6 +5,7 @@ spline: form isComponent: true --- + ## 引入 全局引入,在 miniprogram 根目录下的`app.json`中配置,局部引入,在需要引入的页面或组件的`index.json`中配置。 diff --git a/src/search/__test__/index.test.js b/src/search/__test__/index.test.js new file mode 100644 index 000000000..61ad990f0 --- /dev/null +++ b/src/search/__test__/index.test.js @@ -0,0 +1,329 @@ +import simulate from 'miniprogram-simulate'; +import path from 'path'; + +describe('search', () => { + const search = simulate.load(path.resolve(__dirname, `../search`), 't-search', { + less: true, + rootPath: path.resolve(__dirname, '../..'), + }); + + describe('Props', () => { + it(':action string', () => { + const id = simulate.load({ + template: ``, + usingComponents: { + 't-search': search, + }, + data: { + action: '提交', + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $search = comp.querySelector('.search >>> .t-search__search-action'); + expect($search.dom.textContent.trim()).toBe('提交'); + }); + + it(':action slot', () => { + const id = simulate.load({ + template: `取消`, + usingComponents: { + 't-search': search, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + const $search = comp.querySelector('.search >>> .search-action'); + expect($search.dom.textContent.trim()).toBe('取消'); + }); + + it(':center', () => { + const id = simulate.load({ + template: ``, + usingComponents: { + 't-search': search, + }, + data: { + center: true, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $inputBox = comp.querySelector('.search >>> .t-search__input-box'); + expect($inputBox.dom.getAttribute('class').includes('t-search__input-box--center')); + + const $input = comp.querySelector('.search >>> .t-class-input'); + expect( + $input + .toJSON() + .attrs.filter((v) => v.name === 'placeholderClass')[0] + .value.includes('t-search__placeholder--center'), + ).toBeTruthy(); + }); + + it(':label', () => { + const id = simulate.load({ + template: ``, + usingComponents: { + 't-search': search, + }, + data: { + label: 'TDesign', + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $search = comp.querySelector('.search >>> .t-search__label'); + expect($search.dom.textContent.trim()).toBe('TDesign'); + }); + + it(':placeholder', () => { + const id = simulate.load({ + template: ``, + usingComponents: { + 't-search': search, + }, + data: { + placeholder: 'TDesign MiniProgram', + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $input = comp.querySelector('.search >>> .t-class-input'); + expect( + $input + .toJSON() + .attrs.filter((v) => v.name === 'placeholder')[0] + .value.includes('TDesign MiniProgram'), + ).toBeTruthy(); + }); + + it(':left-icon & right-icon', () => { + const id = simulate.load({ + template: ``, + usingComponents: { + 't-search': search, + }, + data: { + leftIcon: 'add-circle', + rightIcon: 'caret-right', + value: 'test', + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $leftIcon = comp.querySelector('.search >>> .t-icon-add-circle'); + expect($leftIcon).toBeDefined(); + + const $rightIcon = comp.querySelector('.search >>> .t-icon-caret-right'); + expect($rightIcon).toBeDefined(); + }); + + it(':shape', () => { + const id = simulate.load({ + template: ``, + usingComponents: { + 't-search': search, + }, + data: { + shape: 'square', + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $inputBox = comp.querySelector('.search >>> .t-search__input-box'); + expect($inputBox.dom.getAttribute('class').includes('t-search__input-box--square')).toBeTruthy(); + + comp.setData({ + shape: 'round', + }); + expect($inputBox.dom.getAttribute('class').includes('t-search__input-box--round')).toBeTruthy(); + }); + }); + + describe('Event', () => { + it(':action-click', async () => { + const handler = jest.fn(); + + const id = simulate.load({ + template: ``, + usingComponents: { + 't-search': search, + }, + data: { + action: '提交', + }, + methods: { + handler, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $action = comp.querySelector('.search >>> .t-search__search-action'); + $action.dispatchEvent('tap'); + await simulate.sleep(20); + expect(handler).toHaveBeenCalledTimes(1); + }); + + it(':clear', async () => { + let val; + const onClear = jest.fn((e) => { + val = e.detail.value; + }); + const id = simulate.load({ + template: ``, + usingComponents: { + 't-search': search, + }, + data: { + value: '搜索', + }, + methods: { + onClear, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $clear = comp.querySelector('.search >>> .t-search__right'); + $clear.dispatchEvent('tap'); + await simulate.sleep(20); + expect(onClear).toHaveBeenCalledTimes(1); + expect(val).toBe(''); + }); + + it(':submit', async () => { + let val; + const onSubmit = jest.fn((e) => { + val = e.detail.value; + }); + const id = simulate.load({ + template: ``, + usingComponents: { + 't-search': search, + }, + data: { + value: '测试Search', + }, + methods: { + onSubmit, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $input = comp.querySelector('.search >>> .t-class-input'); + $input.dispatchEvent('confirm', { detail: { value: '测试Search' } }); + await simulate.sleep(20); + expect(onSubmit).toHaveBeenCalledTimes(1); + expect(val).toBe('测试Search'); + }); + + it(':change', async () => { + let val; + const onChange = jest.fn((e) => { + val = e.detail.value; + }); + + const id = simulate.load({ + template: ``, + usingComponents: { + 't-search': search, + }, + data: { + value: '搜索框', + }, + methods: { + onChange, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $input = comp.querySelector('.search >>> .t-class-input'); + $input.dispatchEvent('input', { detail: { value: '搜索' } }); + await simulate.sleep(20); + expect(onChange).toHaveBeenCalledTimes(1); + expect(val).toBe('搜索'); + + $input.dispatchEvent('input', { detail: { value: '搜索1' } }); + await simulate.sleep(20); + expect(onChange).toHaveBeenCalledTimes(2); + expect(val).toBe('搜索1'); + }); + + it(':blur', async () => { + let type; + let val; + const onBlur = jest.fn(); + const id = simulate.load({ + template: ``, + usingComponents: { + 't-search': search, + }, + data: { + leftIcon: 'add-circle', + }, + methods: { + onBlur, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + comp.addEventListener('blur', (evt) => { + type = evt.type; + val = evt.detail.value; + comp.removeEventListener('blur'); + }); + + const $input = comp.querySelector('.search >>> .t-class-input'); + $input.dispatchEvent('blur', { detail: { value: 'blur text' } }); + await simulate.sleep(20); + expect(type).toBe('blur'); + expect(val).toBe('blur text'); + expect(onBlur).toHaveBeenCalledTimes(2); + }); + + it(':focus', async () => { + let type; + let val; + const onFocus = jest.fn(); + const onBlur = jest.fn(); + const id = simulate.load({ + template: ``, + usingComponents: { + 't-search': search, + }, + data: { + leftIcon: 'add-circle', + }, + methods: { + onFocus, + onBlur, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + comp.addEventListener('focus', (evt) => { + type = evt.type; + val = evt.detail.value; + comp.removeEventListener('focus'); + }); + + const $input = comp.querySelector('.search >>> .t-class-input'); + $input.dispatchEvent('focus', { detail: { value: 'focus text' } }); + await simulate.sleep(20); + expect(type).toBe('focus'); + expect(val).toBe('focus text'); + expect(onFocus).toHaveBeenCalledTimes(2); + }); + }); +}); diff --git a/src/steps/__test__/index.js b/src/steps/__test__/index.js new file mode 100644 index 000000000..d4eb46b50 --- /dev/null +++ b/src/steps/__test__/index.js @@ -0,0 +1,38 @@ +Component({ + data: { + current1: 0, + current2: 0, + layout: 'horizontal', + readonly: false, + theme: 'default', + currentSub: '1-0', + subStepItems1: [ + { + title: '二级步骤描述', + status: 'process', + }, + { + title: '二级步骤描述', + status: 'finish', + }, + ], + subStepItems2: [ + { + title: '二级步骤描述', + status: 'process', + }, + { + title: '二级步骤描述', + status: 'error', + }, + ], + }, + methods: { + onChange1(e) { + this.setData({ current1: e.detail.current }); + }, + onChange2(e) { + this.setData({ current2: e.detail.current }); + }, + }, +}); diff --git a/src/steps/__test__/index.json b/src/steps/__test__/index.json new file mode 100644 index 000000000..5c615d839 --- /dev/null +++ b/src/steps/__test__/index.json @@ -0,0 +1,6 @@ +{ + "usingComponents": { + "t-steps": "../steps", + "t-step-item": "../step-item" + } +} diff --git a/src/steps/__test__/index.test.js b/src/steps/__test__/index.test.js new file mode 100644 index 000000000..d8b395596 --- /dev/null +++ b/src/steps/__test__/index.test.js @@ -0,0 +1,127 @@ +import simulate from 'miniprogram-simulate'; +import path from 'path'; + +describe('Steps', () => { + let comp; + + beforeAll(() => { + const Index = simulate.load(path.resolve(__dirname, `./index`), { + less: true, + }); + comp = simulate.render(Index); + comp.attach(document.body); + }); + + it(': default-current', async () => { + const items = comp.querySelectorAll('.a1 >>> .item'); + ['process', 'default'].forEach((it, index) => { + expect(items[index].data.curStatus).toBe(it); + }); + ['process', 'default'].forEach((it, index) => { + expect(items[index].querySelector('.t-steps-item').dom.classList).toContain(`t-step--t-steps-item--${it}`); + }); + + const icon = items[1].querySelector('.t-steps-item__icon'); + icon.dispatchEvent('tap'); + await simulate.sleep(5); + + ['finish', 'process'].forEach((it, index) => { + expect(items[index].data.curStatus).toBe(it); + }); + + const items2 = comp.querySelectorAll('.a2 >>> .item'); + ['finish', 'process'].forEach((it, index) => { + expect(items2[index].data.curStatus).toBe(it); + }); + ['finish', 'process'].forEach((it, index) => { + expect(items2[index].querySelector('.t-steps-item').dom.classList).toContain(`t-step--t-steps-item--${it}`); + }); + }); + + it(': layout', async () => { + const root = comp.querySelector('.a1 >>> .t-steps'); + + expect(root.dom.classList).toContain('t-steps--t-steps--horizontal'); + + comp.setData({ layout: 'vertical' }); + + expect(root.dom.classList).toContain('t-steps--t-steps--vertical'); + }); + + it(': theme', async () => { + const item = comp.querySelector('.a2 >>> .item >>> .t-step'); + + expect(item.dom.classList).toContain('t-step--t-step--dot-anchor'); + }); + + it(': current', async () => { + const items = comp.querySelectorAll('.b >>> .item'); + ['process', 'default'].forEach((it, index) => { + expect(items[index].data.curStatus).toBe(it); + }); + + const icon = items[1].querySelector('.t-steps-item__icon'); + icon.dispatchEvent('tap'); + await simulate.sleep(5); + + ['finish', 'process'].forEach((it, index) => { + expect(items[index].data.curStatus).toBe(it); + }); + }); + + it(': current-status', async () => { + const items = comp.querySelectorAll('.c >>> .item'); + ['error', 'default'].forEach((it, index) => { + expect(items[index].data.curStatus).toBe(it); + }); + + const icon = items[1].querySelector('.t-steps-item__icon'); + icon.dispatchEvent('tap'); + await simulate.sleep(5); + + ['finish', 'error'].forEach((it, index) => { + expect(items[index].data.curStatus).toBe(it); + }); + }); + + it(': readonly', async () => { + const mockFn = jest.fn(); + const root = comp.querySelector('.d'); + root.addEventListener('change', mockFn); + + const items = comp.querySelectorAll('.d >>> .item'); + const icon = items[1].querySelector('.t-steps-item__icon'); + icon.dispatchEvent('tap'); + await simulate.sleep(5); + + expect(mockFn).toHaveBeenCalled(); + + comp.setData({ readonly: true }); + icon.dispatchEvent('tap'); + await simulate.sleep(5); + + expect(comp.querySelector('.d >>> .t-steps').dom.classList).toContain('t-steps--t-steps--readonly'); + expect(mockFn).toHaveBeenCalledTimes(1); + }); + + it(': sub-step-items(step-item)', async () => { + const subs1 = comp.querySelectorAll('.e1 >>> .item >>> .t-steps-item-sub'); + + expect(subs1.length).toBe(2); + ['process', 'finish'].forEach((it, index) => { + expect(subs1[index].dom.classList).toContain(`t-step--t-steps-item-sub-status--${it}`); + }); + + const subs2 = comp.querySelectorAll('.e2 >>> .item >>> .t-steps-item-sub'); + + ['process', 'error'].forEach((it, index) => { + expect(subs2[index].dom.classList).toContain(`t-step--t-steps-item-sub-status--${it}`); + }); + }); + + it(': status(step-item)', async () => { + const item = comp.querySelector('.f >>> .item >>> .t-steps-item'); + + expect(item.dom.classList).toContain('t-step--t-steps-item--error'); + }); +}); diff --git a/src/steps/__test__/index.wxml b/src/steps/__test__/index.wxml new file mode 100644 index 000000000..28f7de85d --- /dev/null +++ b/src/steps/__test__/index.wxml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/switch/README.md b/src/switch/README.md index 81d39d15c..d89fd402d 100644 --- a/src/switch/README.md +++ b/src/switch/README.md @@ -5,6 +5,7 @@ spline: form isComponent: true --- + ## 引入 全局引入,在 miniprogram 根目录下的`app.json`中配置,局部引入,在需要引入的页面或组件的`index.json`中配置。 diff --git a/src/switch/__test__/__snapshots__/index.test.js.snap b/src/switch/__test__/__snapshots__/index.test.js.snap new file mode 100644 index 000000000..8742cc591 --- /dev/null +++ b/src/switch/__test__/__snapshots__/index.test.js.snap @@ -0,0 +1,22 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`switch Props :base 1`] = ` +
+ + + + + + + +
+`; diff --git a/src/switch/__test__/index.test.js b/src/switch/__test__/index.test.js new file mode 100644 index 000000000..d6ac518f3 --- /dev/null +++ b/src/switch/__test__/index.test.js @@ -0,0 +1,226 @@ +import simulate from 'miniprogram-simulate'; +import path from 'path'; +import { hex2Rgb } from '../../../test/utils/colors'; + +// TODO size 未实现 loading 未实现 + +describe('switch', () => { + const switchComp = simulate.load(path.resolve(__dirname, `../switch`), 't-switch', { + less: true, + rootPath: path.resolve(__dirname, '../..'), + }); + + describe('Props', () => { + it(':base', () => { + const id = simulate.load({ + template: ``, + usingComponents: { + 't-switch': switchComp, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + expect(comp.toJSON()).toMatchSnapshot(); + }); + + it(':disabled', async () => { + const onChange = jest.fn(); + const id = simulate.load({ + template: ``, + usingComponents: { + 't-switch': switchComp, + }, + data: { + disabled: true, + colors: null, + }, + methods: { + onChange, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $body = comp.querySelector('.switch >>> .t-switch__body'); + const $dot = comp.querySelector('.switch >>> .t-switch__dot'); + expect($body.dom.getAttribute('class').includes('t-switch__body--disabled')).toBeTruthy(); + + $body.dispatchEvent('tap'); + await simulate.sleep(20); + expect(onChange).not.toHaveBeenCalled(); + + $dot.dispatchEvent('tap'); + await simulate.sleep(20); + expect(onChange).not.toHaveBeenCalled(); + + comp.setData({ disabled: false }); + await simulate.sleep(20); + expect($body.dom.getAttribute('class').includes('t-switch__body--disabled')).toBeFalsy(); + }); + + it(':label', async () => { + const id = simulate.load({ + template: ``, + usingComponents: { + 't-switch': switchComp, + }, + data: { + label: '', + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $label = comp.querySelector('.switch >>> .t-switch__label'); + expect($label).toBeUndefined(); + + comp.setData({ + label: '开关的标签', + }); + await simulate.sleep(20); + const $label2 = comp.querySelector('.switch >>> .t-switch__label'); + expect($label2.dom.textContent).toBe('开关的标签'); + }); + + it(':defaultValue', async () => { + const id = simulate.load({ + template: ``, + usingComponents: { + 't-switch': switchComp, + }, + data: { + defaultValue: true, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $switch = comp.querySelector('.switch'); + expect($switch.instance.data.value).toBeTruthy(); + + const $body = comp.querySelector('.switch >>> .t-switch__body'); + expect($body.dom.style.backgroundColor).toBe(hex2Rgb('#0052d9')); + }); + + it(':colors two', async () => { + const id = simulate.load({ + template: ``, + usingComponents: { + 't-switch': switchComp, + }, + data: { + colors: ['#1e80ff', '#8e1280'], + value: true, + disabled: false, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $body = comp.querySelector('.switch >>> .t-switch__body'); + await simulate.sleep(20); + expect($body.dom.style.backgroundColor).toBe(hex2Rgb('#1e80ff')); + + comp.setData({ value: false }); + await simulate.sleep(200); + expect($body.dom.style.backgroundColor).toBe(hex2Rgb('#8e1280')); + }); + + it(':colors one', async () => { + const id = simulate.load({ + template: ``, + usingComponents: { + 't-switch': switchComp, + }, + data: { + colors: ['#c0b8e9'], + defaultValue: true, + disabled: false, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $body = comp.querySelector('.switch >>> .t-switch__body'); + await simulate.sleep(20); + expect($body.dom.style.backgroundColor).toBe(hex2Rgb('#c0b8e9')); + + $body.dispatchEvent('tap'); + await simulate.sleep(200); + expect($body.dom.style.backgroundColor).toBe('rgba(0, 0, 0, 0.26)'); + + comp.setData({ disabled: true }); + $body.dispatchEvent('tap'); + await simulate.sleep(200); + expect($body.dom.style.backgroundColor).toBe('rgba(0, 0, 0, 0.26)'); + }); + + it(':custom-value', async () => { + let val; + const onChange = jest.fn((e) => { + val = e.detail; + }); + const id = simulate.load({ + template: ``, + usingComponents: { + 't-switch': switchComp, + }, + data: { + customValue: [false, true], // [打开时的值,关闭时的值] + defaultValue: true, + }, + methods: { + onChange, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $switch = comp.querySelector('.switch'); + expect($switch.instance.data.value).toBe(true); + + const $body = comp.querySelector('.switch >>> .t-switch__body'); + $body.dispatchEvent('tap'); + await simulate.sleep(20); + expect(val).toStrictEqual({ value: false }); + }); + }); + + describe('Event', () => { + it(':change', async () => { + let value; + const onChange = jest.fn((e) => { + value = e.detail; + }); + const id = simulate.load({ + template: ``, + usingComponents: { + 't-switch': switchComp, + }, + data: { + defaultValue: false, + }, + methods: { + onChange, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + // body 触发事件 + const $body = comp.querySelector('.switch >>> .t-switch__body'); + expect($body.dom.style.backgroundColor).toBe('rgba(0, 0, 0, 0.26)'); + $body.dispatchEvent('tap'); + await simulate.sleep(20); + expect(onChange).toHaveBeenCalledTimes(1); + expect(value).toStrictEqual({ value: true }); + + // dot 触发事件 + const $dot = comp.querySelector('.switch >>> .t-switch__dot'); + $dot.dispatchEvent('tap'); + await simulate.sleep(20); + expect(onChange).toHaveBeenCalledTimes(2); + expect(value).toStrictEqual({ value: false }); + }); + }); +}); diff --git a/src/switch/props.ts b/src/switch/props.ts index 2efe65dd0..87beb1c16 100644 --- a/src/switch/props.ts +++ b/src/switch/props.ts @@ -37,14 +37,14 @@ const props: TdSwitchProps = { }, /** 开关值 */ value: { - type: String, - optionalTypes: [Number, Boolean], + type: Boolean, + optionalTypes: [Number, String], value: null, }, /** 开关值,非受控属性 */ defaultValue: { - type: String, - optionalTypes: [Number, Boolean], + type: Boolean, + optionalTypes: [Number, String], value: null, }, }; diff --git a/src/switch/type.ts b/src/switch/type.ts index d50236f82..cbcb795d1 100644 --- a/src/switch/type.ts +++ b/src/switch/type.ts @@ -55,16 +55,16 @@ export interface TdSwitchProps { * 开关值 */ value?: { - type: StringConstructor; - optionalTypes: Array; + type: BooleanConstructor; + optionalTypes: Array; value?: SwitchValue; }; /** * 开关值,非受控属性 */ defaultValue?: { - type: StringConstructor; - optionalTypes: Array; + type: BooleanConstructor; + optionalTypes: Array; value?: SwitchValue; }; } diff --git a/src/tab-bar/_example/custom/index.wxss b/src/tab-bar/_example/custom/index.wxss index 88ae14432..5434b8be3 100644 --- a/src/tab-bar/_example/custom/index.wxss +++ b/src/tab-bar/_example/custom/index.wxss @@ -1,7 +1,7 @@ .wrapper { - --t-tab-bar-border-color: gray; - --t-tab-bar-bg-color: #eee; - --t-tab-bar-hover-color: #ddd; - --t-tab-bar-item-color: #bbb; - --t-tab-bar-item-active-color: #333; + --td-tab-bar-border-color: gray; + --td-tab-bar-bg-color: #eee; + --td-tab-bar-hover-color: #ddd; + --td-tab-bar-item-color: #bbb; + --td-tab-bar-item-active-color: #333; } \ No newline at end of file diff --git a/src/toast/README.en-US.md b/src/toast/README.en-US.md new file mode 100644 index 000000000..90969a600 --- /dev/null +++ b/src/toast/README.en-US.md @@ -0,0 +1,25 @@ +:: BASE_DOC :: + +## API + +### Toast Props + +name | type | default | description | required +-- | -- | -- | -- | -- +direction | String | row | options:row/column | N +duration | Number | 2000 | \- | N +external-classes | Array | - | `['t-class']` | N +icon | String | - | \- | N +message | String / Slot | - | \- | N +overlay-props | Object | {} | \- | N +placement | String | middle | options: top/middle/bottom | N +prevent-scroll-through | Boolean | false | \- | N +show-overlay | Boolean | false | \- | N +theme | String | - | options:loading/success/fail | N + +### Toast Events + +name | params | description +-- | -- | -- +close | \- | \- +destory | \- | \- diff --git a/src/toast/README.md b/src/toast/README.md index cd0161de7..e46283c61 100644 --- a/src/toast/README.md +++ b/src/toast/README.md @@ -47,5 +47,12 @@ message | String / Slot | - | 弹窗显示文字 | N overlay-props | Object | {} | 遮罩层属性,透传至 Overlay | N placement | String | middle | 弹窗展示位置。可选项: top/middle/bottom | N prevent-scroll-through | Boolean | false | 防止滚动穿透,即不允许点击和滚动 | N -show-overlay | Boolean | true | 是否显示遮罩层 | N +show-overlay | Boolean | false | 是否显示遮罩层 | N theme | String | - | 提示类型。可选项:loading/success/fail | N + +### Toast Events + +名称 | 参数 | 描述 +-- | -- | -- +close | - | 轻提示隐藏的时候触发 +destory | - | 轻提示销毁的时候触发 diff --git a/src/toast/__test__/index.test.js b/src/toast/__test__/index.test.js new file mode 100644 index 000000000..d16c3432a --- /dev/null +++ b/src/toast/__test__/index.test.js @@ -0,0 +1,44 @@ +import simulate from 'miniprogram-simulate'; +import path from 'path'; + +describe('toast', () => { + const toast = simulate.load(path.resolve(__dirname, `../toast`), 't-toast', { + less: true, + rootPath: path.resolve(__dirname, '../..'), + }); + + it(':base', async () => { + const close = jest.fn(); + const destory = jest.fn(); + const id = simulate.load({ + template: ``, + methods: { + close, + destory, + }, + usingComponents: { + 't-toast': toast, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $toast = comp.querySelector('#toast'); + + $toast.instance.show({ message: 'test' }); + + expect($toast.querySelector('.t-toast__text').dom.textContent).toBe('test'); + + $toast.instance.hide(); + + await simulate.sleep(300); + + expect(close).toHaveBeenCalledTimes(1); + + comp.detach(); + + await simulate.sleep(0); + + expect(destory).toHaveBeenCalledTimes(1); + }); +}); diff --git a/src/toast/index.ts b/src/toast/index.ts index 2f7628afe..540dec4b2 100644 --- a/src/toast/index.ts +++ b/src/toast/index.ts @@ -14,6 +14,7 @@ export type ToastOptionsType = { placement?: ToastPositionType; preventScrollThrough?: boolean; direction?: ToastDirectionType; + close?: () => T; }; const getInstance = (context?: Context, selector = '#t-toast') => { diff --git a/src/toast/toast.ts b/src/toast/toast.ts index 8d3f09ffe..2db2da218 100644 --- a/src/toast/toast.ts +++ b/src/toast/toast.ts @@ -78,6 +78,8 @@ export default class Toast extends SuperComponent { this.setData({ inserted: false, }); + this.data?.close?.(); + this.triggerEvent('close'); }, 300); }, @@ -90,6 +92,7 @@ export default class Toast extends SuperComponent { clearTimeout(this.hideTimer); this.hideTimer = null; } + this.triggerEvent('destory'); }, }; } diff --git a/src/toast/type.ts b/src/toast/type.ts index 3ed2d78ce..fd387b940 100644 --- a/src/toast/type.ts +++ b/src/toast/type.ts @@ -69,7 +69,7 @@ export interface TdToastProps { }; /** * 是否显示遮罩层 - * @default true + * @default false */ showOverlay?: { type: BooleanConstructor; diff --git a/test/utils/colors.js b/test/utils/colors.js index acca56424..507adbc83 100644 --- a/test/utils/colors.js +++ b/test/utils/colors.js @@ -1,5 +1,5 @@ // 将rgb颜色转成hex -function rGB2Hex(color) { +function rgb2Hex(color) { const rgb = color.split(','); const r = parseInt(rgb[0].split('(')[1], 10); const g = parseInt(rgb[1], 10); @@ -26,6 +26,6 @@ function hex2Rgb(hex) { } module.exports = { - rGB2Hex, + rgb2Hex, hex2Rgb, }; From ff778851ea77a275fe1e48c732d88424d0fe21e3 Mon Sep 17 00:00:00 2001 From: CodingOnStar <447357187@qq.com> Date: Mon, 29 Aug 2022 10:38:28 +0800 Subject: [PATCH 4/6] =?UTF-8?q?fix(tab):=20=E6=94=B9=E5=8A=A8=E7=8E=B0?= =?UTF-8?q?=E6=9C=89=E7=9A=84tab=E6=BB=9A=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #781 --- src/tabs/tabs.ts | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/tabs/tabs.ts b/src/tabs/tabs.ts index 698c73d60..85d528810 100644 --- a/src/tabs/tabs.ts +++ b/src/tabs/tabs.ts @@ -140,6 +140,19 @@ export default class Tabs extends SuperComponent { } } + calcScrollOffset( + containerWidth: number, + targetLeft: number, + targetWidth: number, + offset: number, + currentIndex: number, + ) { + if (offset + targetLeft > containerWidth / 2) { + return currentIndex * targetWidth - (1 / 2) * containerWidth + targetWidth / 2; + } + return 0; + } + setTrack() { if (!this.properties.showBottomLine) return; const { children } = this; @@ -161,8 +174,15 @@ export default class Tabs extends SuperComponent { } if (this.containerWidth) { + const offset = this.calcScrollOffset( + this.containerWidth, + rect.left, + rect.width, + this.data.offset, + currentIndex, + ); this.setData({ - itemId: `item${rect.dataset.index}`, + offset, }); } From c4aa8f7c70bdcb2e9e03a26c3475ab0500c204e3 Mon Sep 17 00:00:00 2001 From: CodingOnStar <447357187@qq.com> Date: Mon, 29 Aug 2022 10:41:37 +0800 Subject: [PATCH 5/6] =?UTF-8?q?fix(tab):=20=E5=8E=BB=E9=99=A4scroll-into-v?= =?UTF-8?q?iew?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #781 --- src/tabs/tabs.ts | 2 +- src/tabs/tabs.wxml | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/tabs/tabs.ts b/src/tabs/tabs.ts index 85d528810..d48d74256 100644 --- a/src/tabs/tabs.ts +++ b/src/tabs/tabs.ts @@ -69,7 +69,7 @@ export default class Tabs extends SuperComponent { isScrollY: false, direction: 'X', animate: { duration: 0 }, - itemId: 'item0', + offset: 0, }; created() { diff --git a/src/tabs/tabs.wxml b/src/tabs/tabs.wxml index 4b5fdf660..e1ee52593 100644 --- a/src/tabs/tabs.wxml +++ b/src/tabs/tabs.wxml @@ -16,14 +16,12 @@ scroll-x="{{isScrollX}}" scroll-y="{{isScrollY}}" scroll-with-animation - scroll-into-view="{{itemId}}" > From d7638f1ddfec7a13cd9e28f2c5098571ce537672 Mon Sep 17 00:00:00 2001 From: CodingOnStar <447357187@qq.com> Date: Mon, 29 Aug 2022 10:55:00 +0800 Subject: [PATCH 6/6] =?UTF-8?q?fix(n):=20=E7=82=B9=E5=87=BBtab=E5=90=8E?= =?UTF-8?q?=E5=B1=85=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 点击后,前移动到视口中最左侧,然后右移一半,再向左移动一半tab的长度 #781 --- src/tabs/tabs.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/tabs/tabs.ts b/src/tabs/tabs.ts index d48d74256..d44fea6e6 100644 --- a/src/tabs/tabs.ts +++ b/src/tabs/tabs.ts @@ -147,10 +147,7 @@ export default class Tabs extends SuperComponent { offset: number, currentIndex: number, ) { - if (offset + targetLeft > containerWidth / 2) { - return currentIndex * targetWidth - (1 / 2) * containerWidth + targetWidth / 2; - } - return 0; + return currentIndex * targetWidth - (1 / 2) * containerWidth + targetWidth / 2; } setTrack() {