fix(notification): NotificationReactive is not writable (#878)

* fix(notification): NotificationReactive cannot write

* fix: use mutable to remove readonly

* fix: notification test

Co-authored-by: yugang.cao <yugang.cao@tusimple.ai>
Co-authored-by: 07akioni <07akioni2@gmail.com>
This commit is contained in:
Yugang Cao 2021-08-17 00:29:48 +08:00 committed by GitHub
parent 7ef5b8d0a8
commit 672ed322a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 130 additions and 18 deletions

View File

@ -1,5 +1,11 @@
# CHANGELOG
## Pending
### Fixes
- Fix `n-notification`'s exported `NotificationReactive` type is not writable, closes [#876](https://github.com/TuSimple/naive-ui/issues/876).
### Feats
- `n-input-number` add `clearable` prop.

View File

@ -1,5 +1,11 @@
# CHANGELOG
## Pending
### Fixes
- 修复 `n-notification` 导出的 `NotificationReactive` 类型不可变,关闭 [#876](https://github.com/TuSimple/naive-ui/issues/876)
### Feats
- `n-input-number` 新增 `clearable` 属性

View File

@ -20,7 +20,7 @@ export {
largerSize,
getTitleAttribute
} from './naive'
export type { ExtractPublicPropTypes, ExtractInternalPropTypes } from './naive'
export type { ExtractPublicPropTypes, ExtractInternalPropTypes, Mutable } from './naive'
export { formatLength } from './css'
export { createKey } from './cssr'
export * from './composable'

View File

@ -5,3 +5,4 @@ export type {
ExtractPublicPropTypes,
ExtractInternalPropTypes
} from './extract-public-props'
export type { Mutable } from './mutable'

View File

@ -0,0 +1,3 @@
export type Mutable<T> = {
-readonly [P in keyof T]: T[P] extends ReadonlyArray<infer U> ? Array<Mutable<U>> : Mutable<T[P]>
}

View File

@ -20,9 +20,11 @@ export const notificationEnvOptions = {
onLeave: Function as PropType<() => void>,
onAfterEnter: Function as PropType<() => void>,
onAfterLeave: Function as PropType<() => void>,
// deprecated
/** @deprecated */
onHide: Function as PropType<() => void>,
/** @deprecated */
onAfterShow: Function as PropType<() => void>,
/** @deprecated */
onAfterHide: Function as PropType<() => void>
} as const
@ -79,12 +81,8 @@ export default defineComponent({
void el.offsetHeight
}
function handleAfterLeave (): void {
const {
onAfterLeave,
onInternalAfterLeave,
onAfterHide,
internalKey
} = props
const { onAfterLeave, onInternalAfterLeave, onAfterHide, internalKey } =
props
if (onAfterLeave) onAfterLeave()
onInternalAfterLeave(internalKey)
// deprecated

View File

@ -16,7 +16,7 @@ import {
import { createId } from 'seemly'
import { useConfig, useTheme } from '../../_mixins'
import type { MergedTheme, ThemeProps } from '../../_mixins'
import { ExtractPublicPropTypes, omit } from '../../_utils'
import { ExtractPublicPropTypes, omit, Mutable } from '../../_utils'
import { notificationLight, NotificationTheme } from '../styles'
import NotificationContainer from './NotificationContainer'
import NotificationEnvironment, {
@ -63,7 +63,7 @@ export type NotificationReactive = {
readonly hide: () => void
/** @deprecated */
readonly deactivate: () => void
} & NotificationOptions
} & Mutable<NotificationOptions>
interface NotificationRef {
hide: () => void

View File

@ -1,8 +0,0 @@
import { mount } from '@vue/test-utils'
import { NNotificationProvider } from '../index'
describe('n-notification', () => {
it('should work with import on demand', () => {
mount(NNotificationProvider)
})
})

View File

@ -0,0 +1,106 @@
import { mount } from '@vue/test-utils'
import { defineComponent, h, ref, Ref, nextTick } from 'vue'
import {
NNotificationProvider,
useNotification,
NotificationReactive
} from '../index'
const Provider = defineComponent({
render () {
return <NNotificationProvider>{this.$slots}</NNotificationProvider>
}
})
describe('n-notification', () => {
it('should work with import on demand', () => {
mount(NNotificationProvider)
})
it('should have correct type', () => {
const Test = defineComponent({
setup () {
const notification = useNotification()
notification.info({
title: 'info'
})
notification.success({
title: 'success'
})
},
render () {
return null
}
})
const wrapper = mount(() => (
<Provider>{{ default: () => <Test /> }}</Provider>
))
wrapper.unmount()
})
it('can change content', (done) => {
const changeContent = jest.fn((nRef: Ref) => {
nRef.value.content = 'change info'
})
const Test = defineComponent({
setup () {
const nRef = ref<NotificationReactive | null>(null)
const notification = useNotification()
nRef.value = notification.info({
title: 'info',
content: 'info'
})
setTimeout(() => {
nRef.value && changeContent(nRef)
})
},
render () {
return null
}
})
const wrapper = mount(() => (
<Provider>{{ default: () => <Test /> }}</Provider>
))
void nextTick(() => {
expect(
document.querySelector('.n-notification-main__content')?.textContent
).toEqual('info')
setTimeout(() => {
expect(changeContent).toHaveBeenCalled()
expect(
document.querySelector('.n-notification-main__content')?.textContent
).toEqual('change info')
wrapper.unmount()
done()
}, 1000)
})
})
it('should work with duration', (done) => {
const Test = defineComponent({
setup () {
const notification = useNotification()
notification.info({
title: 'info',
content: 'info',
duration: 1000
})
},
render () {
return null
}
})
const wrapper = mount(() => (
<Provider>{{ default: () => <Test /> }}</Provider>
))
void nextTick(() => {
setTimeout(() => {
expect(document.querySelector('.n-notification')).not.toEqual(null)
}, 500)
setTimeout(() => {
expect(document.querySelector('.n-notification')).toBe(null)
wrapper.unmount()
done()
}, 1200)
})
})
})