Skip to content

Commit

Permalink
Merge branch 'master' of github.com:FightingDesign/fighting-design
Browse files Browse the repository at this point in the history
  • Loading branch information
Tyh2001 committed May 2, 2024
2 parents f82aad2 + 5198f0a commit 488ba58
Show file tree
Hide file tree
Showing 5 changed files with 211 additions and 16 deletions.
2 changes: 1 addition & 1 deletion docs/components/message.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@

此外,`Message` 拥有可控的 duration, 默认的关闭时间为 `2500 毫秒`,当把这个属性的值设置为 0 便表示该消息不会被自动关闭。

可以传递 `close-btn` 属性来自定义关闭按钮,支持字符串与 `VNode`
可以传递 `close-btn` 属性来自定义关闭按钮,支持字符串与 `icon`

::: demo

Expand Down
4 changes: 2 additions & 2 deletions docs/components/notification.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@

此外,`Notification` 拥有可控的 duration, 默认的关闭时间为 `2500 毫秒`,当把这个属性的值设置为 0 便表示该消息不会被自动关闭。

可以传递 `close-btn` 属性来自定义关闭按钮,支持字符串与 `VNode`
可以传递 `close-btn` 属性来自定义关闭按钮,支持字符串与 `icon`

::: demo

Expand Down Expand Up @@ -244,7 +244,7 @@
| `background` | 自定义背景色 | string | —— | —— |
| `placement` | 弹出位置 | <a href="#notificationplacement">NotificationPlacement</a> | `top-left` `top-right` `bottom-left` `bottom-right` | top-right |
| `offset` | 偏移距离 | number | —— | 20 |
| `close-btn` | 自定义关闭按钮 | string / <a target="_blank" href="https://cn.vuejs.org/api/render-function.html#h">VNode</a> | —— | —— |
| `close-btn` | 自定义关闭按钮 | string / <a href="/components/interface.html#fightingicon">FightingIcon</a> | —— | —— |
| `z-index` | 层级 | boolean | —— | 1000 |
| `on-close` | 关闭之后回调 | <a href="/components/message.html#messageclose">MessageClose</a> | —— | —— |

Expand Down
215 changes: 205 additions & 10 deletions packages/fighting-design/notification/__test__/notification.spec.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,213 @@
import { h, markRaw } from 'vue'
import { mount } from '@vue/test-utils'
import { describe, expect, test } from 'vitest'
import { vi, describe, expect, test } from 'vitest'
import FNotificationVue from '../src/notification.vue'
import { FIconCross, FIconInfo } from '@fighting-design/fighting-icon'
import { FIGHTING_TYPE } from '../../_tokens'
import type { NotificationPlacement } from '../src/interface'
import type { NotificationProps } from '../src/props'
import type { ComponentPublicInstance } from 'vue'

describe('FNotification', () => {
test('base', async () => {
const NAME = 'Mikoto Misaka'
const AXIOM = 'The electric light dancing at your fingertips is my unchanging faith'

type NotificationInstance = ComponentPublicInstance<NotificationProps & {
visible: boolean
}>

describe('FNotification', () => {
test('basic render', async () => {
const wrapper = mount(FNotificationVue, {
props: { message: '这是一段内容', type: 'success' }
props: {
title: NAME,
message: AXIOM,
}
})
expect(wrapper.find('.f-notification').exists()).toBe(true)
expect(wrapper.find('.f-notification__content').text()).toBe('这是一段内容')
expect(wrapper.find('.f-notification__success').exists()).toBe(true)
await wrapper.setProps({ type: 'primary' })
expect(wrapper.find('.f-notification__primary').exists()).toBe(true)
await wrapper.setProps({ close: true })
expect(wrapper.find('.f-notification__close').exists()).toBe(true)
expect(wrapper.find('.f-notification').attributes('style')).toContain('top: 20px')
expect(wrapper.find('.f-notification__title').text()).toBe(NAME)
expect(wrapper.find('.f-notification__message').text()).toBe(AXIOM)
})

test('should render when the `title` prop is VNode', () => {
const wrapper = mount(FNotificationVue, {
props: {
message: h('span', { class: 'name' }, NAME)
}
})
expect(wrapper.find('.name').text()).toBe(NAME)
})

test('should render when the `message` prop is VNode', () => {
const wrapper = mount(FNotificationVue, {
props: {
message: h('span', { class: 'axiom' }, AXIOM)
}
})
expect(wrapper.find('.axiom').text()).toBe(AXIOM)
})

test('type', () => {
FIGHTING_TYPE.forEach((type) => {
const wrapper = mount(FNotificationVue, {
props: {
type
}
})
expect(wrapper.find(`.f-notification__${type}`).exists()).toBe(true)
})
})

test('round', () => {
const wrapper = mount(FNotificationVue, {
props: {
round: true
}
})
expect(wrapper.find('.f-notification__round').exists()).toBe(true)
})

test('icon', () => {
const wrapper = mount(FNotificationVue, {
props: {
icon: markRaw(FIconInfo)
}
})
expect(wrapper.findComponent(FIconInfo).exists()).toBe(true)
})

test('color', () => {
const wrapper = mount(FNotificationVue, {
props: {
color: 'red'
}
})
expect(wrapper.find('.f-notification').attributes('style')).toContain('--notification-color: red')
})

test('background', () => {
const wrapper = mount(FNotificationVue, {
props: {
background: 'red'
}
})
expect(wrapper.find('.f-notification').attributes('style')).toContain('--notification-background: red')
})

test('offset', () => {
const wrapper = mount(FNotificationVue, {
props: {
offset: 40
}
})
expect(wrapper.find('.f-notification').attributes('style')).toContain('top: 40px')
})

test('zIndex', () => {
const wrapper = mount(FNotificationVue, {
props: {
zIndex: 100
}
})
expect(wrapper.find('.f-notification').attributes('style')).toContain('--notification-z-index: 100')
})

test('placement', () => {
const notificationPlacement: NotificationPlacement[] = ['top-left', 'top-right', 'bottom-left', 'bottom-right']
notificationPlacement.forEach((placement) => {
const wrapper = mount(FNotificationVue, {
props: {
placement
}
})
expect(wrapper.find('.f-notification').classes()).toContain(`f-notification__${placement}`)
})
})

describe('close action', () => {
test('notification should be closable when close button is clicked', async () => {
const wrapper = mount(FNotificationVue, {
props: {
close: true
}
})
const closeBtn = wrapper.find('.f-notification__close')
expect(closeBtn.exists()).toBe(true)
await closeBtn.trigger('click')
expect(wrapper.find('.f-notification').isVisible()).toBe(false)
})

test('closeBtn is a icon', () => {
const wrapper = mount(FNotificationVue, {
props: {
close: true,
closeBtn: markRaw(FIconCross)
}
})
expect(wrapper.findComponent(FIconCross).exists()).toBe(true)
})

test('closeBtn is a string type', () => {
const wrapper = mount(FNotificationVue, {
props: {
close: true,
closeBtn: 'close'
}
})
expect(wrapper.find('.f-notification__close').text()).toBe('close')
})

test('onClose callback should be invoked when the close button is clicked', async () => {
const onClose = vi.fn()
const wrapper = mount(FNotificationVue, {
props: {
close: true,
onClose
}
})
const closeBtn = wrapper.find('.f-notification__close')
await closeBtn.trigger('click')
expect(onClose).toHaveBeenCalled()
})

test('notification should be closable after duration', async () => {
vi.useFakeTimers()
const wrapper = mount(FNotificationVue, {
props: { duration: 1000 }
})
const vm = wrapper.vm as unknown as NotificationInstance
expect(vm.visible).toBe(true)
vi.runAllTimers()
expect(vm.visible).toBe(false)
vi.useRealTimers()
})

test('notification should not be closable when duration is set to 0', async () => {
vi.useFakeTimers()
const wrapper = mount(FNotificationVue, {
props: { duration: 0 }
})
const vm = wrapper.vm as unknown as NotificationInstance
expect(vm.visible).toBe(true)
vi.runAllTimers()
expect(vm.visible).toBe(true)
vi.useRealTimers()
})

test('notification should prevent closure when mouse is hovered over it', async () => {
vi.useFakeTimers()
const wrapper = mount(FNotificationVue, {
props: { duration: 1000 }
})
const vm = wrapper.vm as unknown as NotificationInstance
expect(vm.visible).toBe(true)
await wrapper.find('.f-notification').trigger('mouseenter')
vi.runAllTimers()
expect(vm.visible).toBe(true)
await wrapper.find('.f-notification').trigger('mouseleave')
vi.runAllTimers()
expect(vm.visible).toBe(false)
vi.useRealTimers()
})
})
})
4 changes: 2 additions & 2 deletions packages/fighting-design/notification/src/notification.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
const {
classList,
styleList,
style,
visible,
offsetStyle,
offsetVal,
Expand Down Expand Up @@ -68,7 +68,7 @@
<div
v-show="visible"
:class="classList"
:style="[offsetStyle, styleList]"
:style="[offsetStyle, style]"
@mouseleave="startTime"
@mouseenter="clearTimer"
>
Expand Down
2 changes: 1 addition & 1 deletion packages/fighting-design/notification/src/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export const Props = {
zIndex: setNumberProp(),
/** 自定义关闭按钮 */
closeBtn: {
type: [String, Object] as PropType<VNode | string>,
type: [String, Object] as PropType<FightingIcon | string>,
default: (): null => null
},
/** 关闭之后回调 */
Expand Down

0 comments on commit 488ba58

Please sign in to comment.