diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 7823d80753..e608d55cf2 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -32,7 +32,7 @@ jobs: - name: Lint run: pnpm lint - name: Test - run: pnpm test -- --coverage + run: pnpm test:coverage - name: Upload to codecov.io uses: codecov/codecov-action@v2 with: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d292987627..1cb383100f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -40,8 +40,8 @@ pnpm install Then you can following command to verify your installation. ```shell -pnpm test -pnpm run format +pnpm t +pnpm format ``` ## Getting Started developing diff --git a/jest.config.js b/jest.config.js index e3a2011825..c28e25e446 100644 --- a/jest.config.js +++ b/jest.config.js @@ -3,6 +3,11 @@ */ module.exports = { setupFiles: ['./jest.setup.js'], + testMatch: [ + '**/__tests__/**/*.[jt]s?(x)', + '**/?(*.)+(spec|test).[jt]s?(x)', + '!**/**vitest**', + ], testPathIgnorePatterns: ['/node_modules/', 'dist'], modulePathIgnorePatterns: ['/node_modules/', 'dist', 'cypress'], testEnvironment: 'jsdom', diff --git a/package.json b/package.json index fef8e5c720..f6a6d0f442 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,10 @@ }, "scripts": { "cz": "git-cz", - "test": "jest", + "test": "pnpm test:jest && pnpm test:vitest", + "test:jest": "jest", + "test:vitest": "vitest", + "test:coverage": "vitest --coverage", "prepare:e2e": "if [ ! -d \"docs/.vitepress/dist\" ]; then pnpm run docs:build; fi;", "e2e": "cypress open", "e2e:ci": "cypress run", @@ -96,10 +99,12 @@ "@typescript-eslint/parser": "5.12.0", "@vitejs/plugin-vue": "2.2.2", "@vitejs/plugin-vue-jsx": "1.3.7", + "@vitest/ui": "^0.3.2", "@vue/babel-plugin-jsx": "1.1.1", "@vue/test-utils": "2.0.0-rc.16", "@vue/tsconfig": "0.1.3", "babel-jest": "26.6.3", + "c8": "^7.11.0", "chalk": "4.1.2", "components-helper": "2.0.0", "csstype": "2.6.19", @@ -134,6 +139,7 @@ "type-fest": "2.12.0", "typescript": "4.5.5", "unplugin-vue-define-options": "0.3.1", + "vitest": "^0.3.2", "vue": "3.2.30", "vue-jest": "5.0.0-alpha.10", "vue-router": "4.0.12", diff --git a/packages/constants/package.json b/packages/constants/package.json index ac82cec1d2..81e4ac379c 100644 --- a/packages/constants/package.json +++ b/packages/constants/package.json @@ -1,5 +1,6 @@ { "name": "@element-plus/constants", "private": true, - "license": "MIT" + "license": "MIT", + "main": "index.ts" } diff --git a/packages/hooks/__tests__/use-attrs.spec.ts b/packages/hooks/__tests__/use-attrs.vitest.tsx similarity index 61% rename from packages/hooks/__tests__/use-attrs.spec.ts rename to packages/hooks/__tests__/use-attrs.vitest.tsx index 8fc5122885..9d14d4c0a0 100644 --- a/packages/hooks/__tests__/use-attrs.spec.ts +++ b/packages/hooks/__tests__/use-attrs.vitest.tsx @@ -1,6 +1,7 @@ +import { defineComponent } from 'vue' import { mount } from '@vue/test-utils' +import { describe, it, expect, fn, afterEach, vi } from 'vitest' import { useAttrs } from '../use-attrs' -import type { ComponentOptions } from 'vue' const CLASS = 'a' const WIDTH = '50px' @@ -8,53 +9,50 @@ const TEST_KEY = 'test' const TEST_VALUE = 'fake' const ANOTHER_TEST_VALUE = 'fake1' -const handleClick = jest.fn() +const handleClick = fn() const genComp = ( inheritAttrs = true, excludeListeners = false, excludeKeys: string[] = [] ) => { - return { - template: ` -
- -
- `, + return defineComponent({ inheritAttrs, props: {}, setup() { const attrs = useAttrs({ excludeListeners, excludeKeys }) - - return { - attrs, - } - }, - } -} - -const _mount = (Comp: ComponentOptions) => { - return mount({ - components: { Comp }, - template: ` - `, - methods: { - handleClick, + return () => ( +
+ +
+ ) }, }) } -afterEach(() => { - handleClick.mockClear() -}) +const _mount = (Comp: ReturnType) => { + return mount({ + setup() { + return () => ( + + ) + }, + }) +} describe('useAttrs', () => { - test('class and style should not bind to child node', async () => { + afterEach(() => { + vi.restoreAllMocks() + }) + + it('class and style should not bind to child node', async () => { const wrapper = _mount(genComp()) const container = wrapper.element as HTMLDivElement const span = wrapper.find('span') @@ -70,7 +68,7 @@ describe('useAttrs', () => { expect(handleClick).toBeCalledTimes(2) }) - test("child node's attributes should update when prop change", async () => { + it("child node's attributes should update when prop change", async () => { const wrapper = _mount(genComp()) const span = wrapper.find('span') @@ -78,7 +76,7 @@ describe('useAttrs', () => { expect(span.attributes(TEST_KEY)).toBe(ANOTHER_TEST_VALUE) }) - test('excluded listeners should not bind to child node', async () => { + it('excluded listeners should not bind to child node', async () => { const wrapper = _mount(genComp(true, true)) const span = wrapper.find('span') @@ -87,7 +85,7 @@ describe('useAttrs', () => { expect(handleClick).toBeCalledTimes(1) }) - test('excluded attributes should not bind to child node', async () => { + it('excluded attributes should not bind to child node', async () => { const wrapper = _mount(genComp(true, false, [TEST_KEY])) const span = wrapper.find('span') diff --git a/packages/hooks/__tests__/use-deprecated.spec.ts b/packages/hooks/__tests__/use-deprecated.vitest.ts similarity index 75% rename from packages/hooks/__tests__/use-deprecated.spec.ts rename to packages/hooks/__tests__/use-deprecated.vitest.ts index fbb2874bc9..e6e445f00c 100644 --- a/packages/hooks/__tests__/use-deprecated.spec.ts +++ b/packages/hooks/__tests__/use-deprecated.vitest.ts @@ -1,11 +1,15 @@ import { computed, defineComponent, nextTick } from 'vue' import { mount } from '@vue/test-utils' +import { describe, it, fn, vi, expect, afterEach } from 'vitest' import { debugWarn } from '@element-plus/utils' import { useDeprecated } from '../use-deprecated' -jest.mock('@element-plus/utils/error', () => { +const AXIOM = 'Rem is the best girl' + +vi.mock('@element-plus/utils/error', async () => { return { - debugWarn: jest.fn(), + ...(await vi.importActual('@element-plus/utils/error')), + debugWarn: fn(), } }) @@ -24,14 +28,15 @@ const DummyComponent = defineComponent({ }, computed(() => props.shouldWarn) ) + return () => AXIOM }, - template: `
Rem is the best girl
`, }) describe('useDeprecated', () => { - beforeEach(() => { - ;(debugWarn as jest.Mock).mockClear() + afterEach(() => { + vi.restoreAllMocks() }) + it('should warn when condition is true', async () => { mount(DummyComponent, { props: { diff --git a/packages/hooks/__tests__/use-focus.spec.ts b/packages/hooks/__tests__/use-focus.vitest.ts similarity index 89% rename from packages/hooks/__tests__/use-focus.spec.ts rename to packages/hooks/__tests__/use-focus.vitest.ts index 9a724cea62..bca1e3289e 100644 --- a/packages/hooks/__tests__/use-focus.spec.ts +++ b/packages/hooks/__tests__/use-focus.vitest.ts @@ -1,4 +1,5 @@ import { ref } from 'vue' +import { describe, it, expect } from 'vitest' import { useFocus } from '../use-focus' describe('useFocus', () => { diff --git a/packages/hooks/__tests__/use-form-item.spec.ts b/packages/hooks/__tests__/use-form-item.vitest.tsx similarity index 80% rename from packages/hooks/__tests__/use-form-item.spec.ts rename to packages/hooks/__tests__/use-form-item.vitest.tsx index fd2997df3e..33bb883fb4 100644 --- a/packages/hooks/__tests__/use-form-item.spec.ts +++ b/packages/hooks/__tests__/use-form-item.vitest.tsx @@ -1,6 +1,7 @@ -import { h, provide } from 'vue' +import { defineComponent, provide } from 'vue' import { NOOP } from '@vue/shared' import { mount } from '@vue/test-utils' +import { describe, it, expect } from 'vitest' import { ElButton } from '@element-plus/components' import { elFormKey, @@ -16,23 +17,16 @@ import type { const AXIOM = 'Rem is the best girl' -const Component = { - render() { - return h(ElButton, this.$attrs, { - default: () => [AXIOM], - }) - }, -} - -const mountComponent = (setup = NOOP, options = {}) => { - return mount( - { - ...Component, +const mountComponent = (setup = NOOP, options = {}) => + mount( + defineComponent({ setup, - }, + render() { + return {AXIOM} + }, + }), options ) -} describe('use-form-item', () => { it('should return local value', () => { @@ -44,14 +38,10 @@ describe('use-form-item', () => { const propSize = 'small' const wrapper = mountComponent( () => { - provide(elFormItemKey, { - size: 'large', - } as ElFormItemContext) + provide(elFormItemKey, { size: 'large' } as ElFormItemContext) }, { - props: { - size: propSize, - }, + props: { size: propSize }, } ) diff --git a/packages/hooks/__tests__/use-locale.spec.ts b/packages/hooks/__tests__/use-locale.vitest.tsx similarity index 65% rename from packages/hooks/__tests__/use-locale.spec.ts rename to packages/hooks/__tests__/use-locale.vitest.tsx index 26eace5831..532d2146e9 100644 --- a/packages/hooks/__tests__/use-locale.spec.ts +++ b/packages/hooks/__tests__/use-locale.vitest.tsx @@ -1,46 +1,43 @@ -import { h, nextTick, computed } from 'vue' +import { nextTick, computed, defineComponent } from 'vue' import { mount } from '@vue/test-utils' +import { describe, it, expect, beforeEach, afterEach } from 'vitest' import Chinese from '@element-plus/locale/lang/zh-cn' import English from '@element-plus/locale/lang/en' import { useLocale, buildTranslator } from '../use-locale' import { provideGlobalConfig } from '..' +import type { Language } from '@element-plus/locale' +import type { PropType, ComponentPublicInstance } from 'vue' +import type { VueWrapper } from '@vue/test-utils' -const TestComp = { +const TestComp = defineComponent({ setup() { const { t } = useLocale() - return () => { - return h( - 'div', - { class: 'locale-manifest' }, - t('el.popconfirm.confirmButtonText') - ) - } + return () => ( +
{t('el.popconfirm.confirmButtonText')}
+ ) }, -} +}) describe('use-locale', () => { - let wrapper + let wrapper: VueWrapper + beforeEach(() => { wrapper = mount( { props: { - locale: Object, + locale: Object as PropType, }, components: { 'el-test': TestComp, }, setup(props, { slots }) { provideGlobalConfig(computed(() => ({ locale: props.locale }))) - return () => slots.default() + return () => slots.default?.() }, }, { - props: { - locale: Chinese, - }, - slots: { - default: () => h(TestComp), - }, + props: { locale: Chinese }, + slots: { default: () => }, } ) }) @@ -70,7 +67,7 @@ describe('use-locale', () => { ) }) - test('return key name if not defined', () => { + it('return key name if not defined', () => { const t = buildTranslator(English) expect(t('el.popconfirm.someThing')).toBe('el.popconfirm.someThing') }) diff --git a/packages/hooks/__tests__/use-lockscreen.spec.ts b/packages/hooks/__tests__/use-lockscreen.vitest.tsx similarity index 60% rename from packages/hooks/__tests__/use-lockscreen.spec.ts rename to packages/hooks/__tests__/use-lockscreen.vitest.tsx index 1d6b464bc7..b22dfd528c 100644 --- a/packages/hooks/__tests__/use-lockscreen.spec.ts +++ b/packages/hooks/__tests__/use-lockscreen.vitest.tsx @@ -1,5 +1,6 @@ import { ref, nextTick, defineComponent, onMounted } from 'vue' import { mount } from '@vue/test-utils' +import { describe, it, expect } from 'vitest' import { hasClass } from '@element-plus/utils' import { useLockscreen } from '../use-lockscreen' @@ -13,19 +14,15 @@ const Comp = defineComponent({ onMounted(() => { flag.value = true }) + + return () => undefined }, - template: `
`, }) describe('useLockscreen', () => { - test('should lock screen when trigger is true', async () => { + it('should lock screen when trigger is true', async () => { const wrapper = mount({ - template: ` - - `, - components: { - 'test-comp': Comp, - }, + setup: () => () => , }) await nextTick() expect(hasClass(document.body, kls)).toBe(true) @@ -35,26 +32,17 @@ describe('useLockscreen', () => { expect(hasClass(document.body, kls)).toBe(false) }) - test('should cleanup when unmounted', async () => { - const wrapper = mount({ - template: ` - - `, - data() { - return { - shouldRender: true, - } - }, - components: { - 'test-comp': Comp, - }, + it('should cleanup when unmounted', async () => { + const shouldRender = ref(true) + mount({ + setup: () => () => shouldRender.value ? : undefined, }) await nextTick() expect(hasClass(document.body, kls)).toBe(true) - wrapper.vm.shouldRender = false + shouldRender.value = false await nextTick() expect(hasClass(document.body, kls)).toBe(false) diff --git a/packages/hooks/__tests__/use-modal.spec.ts b/packages/hooks/__tests__/use-modal.vitest.ts similarity index 83% rename from packages/hooks/__tests__/use-modal.spec.ts rename to packages/hooks/__tests__/use-modal.vitest.ts index 798d67c2d4..0da7573aea 100644 --- a/packages/hooks/__tests__/use-modal.spec.ts +++ b/packages/hooks/__tests__/use-modal.vitest.ts @@ -1,12 +1,12 @@ import { ref, nextTick } from 'vue' +import { describe, it, expect, fn } from 'vitest' import { EVENT_CODE } from '@element-plus/constants' - import { useModal } from '../use-modal' describe('useModal', () => { - test('should work when ref value changed', async () => { + it('should work when ref value changed', async () => { const visible = ref(false) - const handleClose = jest.fn() + const handleClose = fn() useModal( { diff --git a/packages/hooks/__tests__/use-model-toggle.spec.ts b/packages/hooks/__tests__/use-model-toggle.vitest.tsx similarity index 75% rename from packages/hooks/__tests__/use-model-toggle.spec.ts rename to packages/hooks/__tests__/use-model-toggle.vitest.tsx index dc328a1127..10394eb887 100644 --- a/packages/hooks/__tests__/use-model-toggle.spec.ts +++ b/packages/hooks/__tests__/use-model-toggle.vitest.tsx @@ -1,21 +1,24 @@ -import { nextTick, ref, h, reactive } from 'vue' +import { nextTick, ref, reactive, defineComponent } from 'vue' import { mount } from '@vue/test-utils' +import { describe, it, expect, fn, beforeEach, afterEach } from 'vitest' import { useModelToggle, useModelToggleProps } from '../use-model-toggle' - -import type { ExtractPropTypes } from 'vue' +import type { VueWrapper } from '@vue/test-utils' const AXIOM = 'Rem is the best girl' -const onShow = jest.fn() -const onHide = jest.fn() +const onShow = fn() +const onHide = fn() let flag = true const shouldProceed = () => flag -const Comp = { - name: 'comp', - props: { ...useModelToggleProps, disabled: Boolean }, - setup(props: ExtractPropTypes) { +const Comp = defineComponent({ + props: { + ...useModelToggleProps, + disabled: Boolean, + }, + + setup(props) { const indicator = ref(false) const { show, hide, toggle } = useModelToggle({ indicator, @@ -26,36 +29,26 @@ const Comp = { }) return () => { - return [ - h( - 'button', - { - class: 'show', - onClick: show, - }, - 'show' - ), - h( - 'button', - { - class: 'hide', - onClick: hide, - }, - 'hide' - ), - h('button', { - class: 'toggle', - onClick: toggle, - }), - - indicator.value || props.modelValue ? h('div', AXIOM) : null, - ] + return ( + <> + + + + {indicator.value || props.modelValue ?
{AXIOM}
: undefined} + + ) } }, -} +}) describe('use-model-toggle', () => { - let wrapper: ReturnType + let wrapper: VueWrapper beforeEach(() => { flag = true wrapper = mount(Comp) @@ -129,33 +122,28 @@ describe('use-model-toggle', () => { it('should bind with modelValue', async () => { wrapper.unmount() + + const model = ref(false) + const disabled = ref(false) wrapper = mount({ - components: { - Comp, - }, - template: ``, - data() { - return { - model: false, - disabled: false, - } - }, + setup: () => () => + , }) expect(wrapper.findComponent(Comp).text()).not.toContain(AXIOM) await wrapper.find('.show').trigger('click') - expect(wrapper.vm.model).toBe(true) + expect(model.value).toBe(true) expect(wrapper.findComponent(Comp).text()).toContain(AXIOM) await wrapper.find('.hide').trigger('click') expect(onHide).toHaveBeenCalledTimes(1) - expect(wrapper.vm.model).toBe(false) + expect(model.value).toBe(false) expect(wrapper.findComponent(Comp).text()).not.toContain(AXIOM) - ;(wrapper.vm.model as any) = true - ;(wrapper.vm.disabled as any) = true + model.value = true + disabled.value = true await nextTick() // when disabled emits false that modifies the model - expect(wrapper.vm.model).toBe(false) + expect(model.value).toBe(false) // should not hide when disabled await wrapper.find('.hide').trigger('click') diff --git a/packages/hooks/__tests__/use-namespace.spec.ts b/packages/hooks/__tests__/use-namespace.spec.ts deleted file mode 100644 index 63c72abf3f..0000000000 --- a/packages/hooks/__tests__/use-namespace.spec.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { h, nextTick } from 'vue' -import { mount } from '@vue/test-utils' -import { useNamespace, provideGlobalConfig } from '..' - -const TestComp = { - setup() { - const ns = useNamespace('table') - return () => { - return h( - 'div', - { - id: 'testId', - class: [ - ns.b(), // return ns + block - ns.b('body'), - ns.e('content'), - ns.m('active'), - ns.be('content', 'active'), - ns.em('content', 'active'), - ns.bem('body', 'content', 'active'), - ns.is('focus'), - ns.e(), // return empty string - ns.m(), // return empty string - ns.be(), // return empty string - ns.em(), // return empty string - ns.bem(), // return empty string - ns.is('hover', undefined), // return empty string - ns.is('clicked', false), // return empty string - ], - }, - 'text' - ) - } - }, -} - -describe('use-locale', () => { - let wrapper - beforeEach(() => { - wrapper = mount( - { - components: { - 'el-test': TestComp, - }, - setup(props, { slots }) { - provideGlobalConfig({ namespace: 'ep' }) - return () => slots.default() - }, - }, - { - slots: { - default: () => h(TestComp), - }, - } - ) - }) - - afterEach(() => { - wrapper.unmount() - }) - - it('should provide bem correctly', async () => { - await nextTick() - expect(wrapper.find('#testId').classes().join('~')).toBe( - [ - 'ep-table', // b() - 'ep-table-body', // b('body') - 'ep-table__content', // e('content') - 'ep-table--active', // m('active') - 'ep-table-content__active', // be('content', 'active') - 'ep-table__content--active', // em('content', 'active') - 'ep-table-body__content--active', // bem('body', 'content', 'active') - 'is-focus', // is('focus') - ].join('~') - ) - }) -}) diff --git a/packages/hooks/__tests__/use-namespace.vitest.tsx b/packages/hooks/__tests__/use-namespace.vitest.tsx new file mode 100644 index 0000000000..df7f0697ff --- /dev/null +++ b/packages/hooks/__tests__/use-namespace.vitest.tsx @@ -0,0 +1,68 @@ +import { defineComponent, nextTick } from 'vue' +import { mount } from '@vue/test-utils' +import { describe, it, expect, beforeEach, afterEach } from 'vitest' +import { useNamespace, provideGlobalConfig } from '..' +import type { VueWrapper } from '@vue/test-utils' + +const TestComp = defineComponent({ + setup() { + const ns = useNamespace('table') + return () => ( +
+ text +
+ ) + }, +}) + +describe('use-locale', () => { + const Comp = defineComponent({ + setup(_props, { slots }) { + provideGlobalConfig({ namespace: 'ep' }) + return () => slots.default?.() + }, + }) + let wrapper: VueWrapper> + beforeEach(() => { + wrapper = mount(Comp, { + slots: { default: () => }, + }) + }) + + afterEach(() => { + wrapper.unmount() + }) + + it('should provide bem correctly', async () => { + await nextTick() + expect(wrapper.find('#testId').classes()).toEqual([ + 'ep-table', // b() + 'ep-table-body', // b('body') + 'ep-table__content', // e('content') + 'ep-table--active', // m('active') + 'ep-table-content__active', // be('content', 'active') + 'ep-table__content--active', // em('content', 'active') + 'ep-table-body__content--active', // bem('body', 'content', 'active') + 'is-focus', // is('focus') + ]) + }) +}) diff --git a/packages/hooks/__tests__/use-prevent-global.ts b/packages/hooks/__tests__/use-prevent-global.vitest.ts similarity index 64% rename from packages/hooks/__tests__/use-prevent-global.ts rename to packages/hooks/__tests__/use-prevent-global.vitest.ts index 83d338a56c..fb907a44b2 100644 --- a/packages/hooks/__tests__/use-prevent-global.ts +++ b/packages/hooks/__tests__/use-prevent-global.vitest.ts @@ -1,44 +1,51 @@ import { ref } from 'vue' -import { on, off } from '@element-plus/utils' +import { + describe, + it, + expect, + beforeAll, + beforeEach, + afterAll, + fn, +} from 'vitest' import triggerEvent from '@element-plus/test-utils/trigger-event' import { usePreventGlobal } from '../use-prevent-global' describe('usePreventGlobal', () => { const evtName = 'keydown' - const evt = jest.fn() + const evtHandler = fn() beforeAll(() => { - on(document.body, evtName, evt) + document.body.addEventListener(evtName, evtHandler) }) beforeEach(() => { - evt.mockClear() + evtHandler.mockClear() }) afterAll(() => { - off(document.body, evtName, evt) + document.body.removeEventListener(evtName, evtHandler) }) it('should prevent global event from happening', () => { const visible = ref(true) - const evt2Trigger = jest.fn().mockReturnValue(true) + const evt2Trigger = fn().mockReturnValue(true) usePreventGlobal(visible, evtName, evt2Trigger) triggerEvent(document.body, evtName) - expect(evt).not.toBeCalled() + expect(evtHandler).not.toBeCalled() expect(evt2Trigger).toHaveBeenCalled() visible.value = false - // clean up }) it('should not prevent global event from happening', () => { const visible = ref(true) - const evt2Trigger = jest.fn().mockReturnValue(false) + const evt2Trigger = fn().mockReturnValue(false) usePreventGlobal(visible, evtName, evt2Trigger) triggerEvent(document.body, evtName) - expect(evt).toHaveBeenCalled() + expect(evtHandler).toHaveBeenCalled() expect(evt2Trigger).toHaveBeenCalled() visible.value = false diff --git a/packages/hooks/__tests__/use-restore-active.spec.ts b/packages/hooks/__tests__/use-restore-active.vitest.ts similarity index 93% rename from packages/hooks/__tests__/use-restore-active.spec.ts rename to packages/hooks/__tests__/use-restore-active.vitest.ts index f55263590f..1c7c57222d 100644 --- a/packages/hooks/__tests__/use-restore-active.spec.ts +++ b/packages/hooks/__tests__/use-restore-active.vitest.ts @@ -1,4 +1,5 @@ import { ref, nextTick } from 'vue' +import { describe, it, expect } from 'vitest' import { useRestoreActive } from '../use-restore-active' describe('useRestoreActive', () => { diff --git a/packages/hooks/__tests__/use-teleport.spec.ts b/packages/hooks/__tests__/use-teleport.vitest.tsx similarity index 63% rename from packages/hooks/__tests__/use-teleport.spec.ts rename to packages/hooks/__tests__/use-teleport.vitest.tsx index 44b8def875..5f37e62b03 100644 --- a/packages/hooks/__tests__/use-teleport.spec.ts +++ b/packages/hooks/__tests__/use-teleport.vitest.tsx @@ -1,11 +1,12 @@ -import { ref, nextTick, h } from 'vue' +import { ref, nextTick, h, defineComponent } from 'vue' import { mount } from '@vue/test-utils' - +import { describe, it, expect, beforeEach, afterEach } from 'vitest' import { useTeleport } from '../use-teleport' +import type { VueWrapper } from '@vue/test-utils' const AXIOM = 'Rem is the best girl' -const Comp = { +const Comp = defineComponent({ setup() { const appendToBody = ref(true) const { showTeleport, hideTeleport, renderTeleport } = useTeleport( @@ -13,39 +14,28 @@ const Comp = { appendToBody ) - return () => { - return [ - h( - 'button', - { - class: 'show', - onClick: showTeleport, - }, - 'show' - ), - h( - 'button', - { - class: 'hide', - onClick: hideTeleport, - }, - 'hide' - ), - h('button', { - class: 'toggle', - onClick: () => { - // toggle append to body. - appendToBody.value = !appendToBody.value - }, - }), - renderTeleport(), - ] - } + return () => ( + <> + + + + {renderTeleport()} + + ) }, -} +}) describe('useModal', () => { - let wrapper: ReturnType + let wrapper: VueWrapper> beforeEach(() => { wrapper = mount(Comp) diff --git a/packages/hooks/__tests__/use-timeout.spec.ts b/packages/hooks/__tests__/use-timeout.vitest.ts similarity index 69% rename from packages/hooks/__tests__/use-timeout.spec.ts rename to packages/hooks/__tests__/use-timeout.vitest.ts index 34ccc68a24..633c08a467 100644 --- a/packages/hooks/__tests__/use-timeout.spec.ts +++ b/packages/hooks/__tests__/use-timeout.vitest.ts @@ -1,4 +1,5 @@ import { mount } from '@vue/test-utils' +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import { useTimeout } from '../use-timeout' const _mount = (cb: () => void) => { @@ -7,29 +8,27 @@ const _mount = (cb: () => void) => { const { cancelTimeout, registerTimeout } = useTimeout() registerTimeout(cb, 0) - return { - cancelTimeout, - } - }, - render() { - return null + return { cancelTimeout } }, + render: () => undefined, }) } -jest.useFakeTimers() - describe('use-timeout', () => { - let wrapper - const cb = jest.fn() beforeEach(() => { - cb.mockClear() + vi.useFakeTimers() wrapper = _mount(cb) }) + afterEach(() => { + vi.restoreAllMocks() + }) + + let wrapper: ReturnType + const cb = vi.fn() it('should register timeout correctly', async () => { expect(cb).not.toHaveBeenCalled() - jest.runOnlyPendingTimers() + vi.runOnlyPendingTimers() expect(cb).toHaveBeenCalled() wrapper.unmount() }) @@ -37,7 +36,7 @@ describe('use-timeout', () => { it('should cancel the timeout correctly', async () => { wrapper.vm.cancelTimeout() - jest.runOnlyPendingTimers() + vi.runOnlyPendingTimers() expect(cb).not.toHaveBeenCalled() wrapper.unmount() @@ -47,7 +46,7 @@ describe('use-timeout', () => { expect(cb).not.toHaveBeenCalled() wrapper.unmount() - jest.runOnlyPendingTimers() + vi.runOnlyPendingTimers() expect(cb).not.toHaveBeenCalled() }) diff --git a/packages/hooks/use-model-toggle/index.ts b/packages/hooks/use-model-toggle/index.ts index 8791f244e5..37efa28110 100644 --- a/packages/hooks/use-model-toggle/index.ts +++ b/packages/hooks/use-model-toggle/index.ts @@ -1,21 +1,30 @@ import { computed, getCurrentInstance, watch, onMounted } from 'vue' import { isFunction } from '@vue/shared' import { isClient } from '@vueuse/core' -import { isBoolean, buildProp, definePropType } from '@element-plus/utils' +import { isBoolean, definePropType, buildProp } from '@element-plus/utils' import type { RouteLocationNormalizedLoaded } from 'vue-router' import type { Ref, ComponentPublicInstance, ExtractPropTypes } from 'vue' -export const createModelToggleComposable = (name: string) => { +const _prop = buildProp({ + type: definePropType(Boolean), + default: null, +} as const) +const _event = buildProp({ + type: definePropType<(val: boolean) => void>(Function), +} as const) + +type _UseModelToggleProps = { + [K in T]: typeof _prop +} & { + [K in `onUpdate:${T}`]: typeof _event +} + +export const createModelToggleComposable = (name: T) => { const useModelToggleProps = { - [name]: buildProp({ - type: definePropType(Boolean), - default: null, - } as const), - [`onUpdate:${name}`]: buildProp({ - type: definePropType<(val: boolean) => void>(Function), - } as const), - } + [name]: _prop, + [`onUpdate:${name}`]: _event, + } as _UseModelToggleProps const useModelToggleEmits = [`update:${name}`] @@ -27,7 +36,9 @@ export const createModelToggleComposable = (name: string) => { onHide, }: ModelToggleParams) => { const instance = getCurrentInstance()! - const props = instance.props as UseModelToggleProps & { disabled: boolean } + const props = instance.props as _UseModelToggleProps & { + disabled: boolean + } const { emit } = instance const updateEventKey = `update:${name}` diff --git a/packages/utils/tests/dom/aria.test.ts b/packages/utils/__tests__/dom/aria.vitest.ts similarity index 96% rename from packages/utils/tests/dom/aria.test.ts rename to packages/utils/__tests__/dom/aria.vitest.ts index d1c99f87c3..3dec9110a7 100644 --- a/packages/utils/tests/dom/aria.test.ts +++ b/packages/utils/__tests__/dom/aria.vitest.ts @@ -1,3 +1,4 @@ +import { describe, it, expect, spyOn } from 'vitest' import { triggerEvent, isFocusable } from '../..' const CE = (tag: string) => document.createElement(tag) @@ -6,7 +7,7 @@ describe('Aria Utils', () => { describe('Trigger Event', () => { it('Util trigger event to trigger event correctly', () => { const div = document.createElement('div') - jest.spyOn(div, 'dispatchEvent') + spyOn(div, 'dispatchEvent') const eventName = 'click' triggerEvent(div, eventName) expect(div.dispatchEvent).toHaveBeenCalled() diff --git a/packages/utils/tests/dom/dom.spec.ts b/packages/utils/__tests__/dom/style.vitest.ts similarity index 98% rename from packages/utils/tests/dom/dom.spec.ts rename to packages/utils/__tests__/dom/style.vitest.ts index 8513438be7..25351909bb 100644 --- a/packages/utils/tests/dom/dom.spec.ts +++ b/packages/utils/__tests__/dom/style.vitest.ts @@ -1,13 +1,12 @@ +import { describe, it, expect } from 'vitest' import { hasClass, addClass, removeClass } from '../..' const getClass = (el: Element) => { - if (!el) { - return '' - } + if (!el) return '' return el.getAttribute('class') } -describe('Dom Utils', () => { +describe('dom style', () => { describe('hasClass', () => { it('Judge whether a Element has a class', () => { const div = document.createElement('div') diff --git a/packages/utils/tests/vue/global-nodes.spec.ts b/packages/utils/__tests__/vue/global-node.vitest.ts similarity index 94% rename from packages/utils/tests/vue/global-nodes.spec.ts rename to packages/utils/__tests__/vue/global-node.vitest.ts index 6aafc24bac..e16816056a 100644 --- a/packages/utils/tests/vue/global-nodes.spec.ts +++ b/packages/utils/__tests__/vue/global-node.vitest.ts @@ -1,3 +1,4 @@ +import { describe, it, expect, afterEach } from 'vitest' import { createGlobalNode, removeGlobalNode, diff --git a/packages/utils/tests/vue/prop.spec.ts b/packages/utils/__tests__/vue/props.vitest.ts similarity index 99% rename from packages/utils/tests/vue/prop.spec.ts rename to packages/utils/__tests__/vue/props.vitest.ts index 4dee9a74b1..1161256908 100644 --- a/packages/utils/tests/vue/prop.spec.ts +++ b/packages/utils/__tests__/vue/props.vitest.ts @@ -2,6 +2,7 @@ import { defineComponent } from 'vue' import { mount } from '@vue/test-utils' +import { describe, it, expect, vi } from 'vitest' import { expectTypeOf } from 'expect-type' import { buildProp, definePropType, mutable, keysOf, buildProps } from '../..' import type { propKey } from '../..' @@ -449,7 +450,7 @@ describe('buildProps', () => { describe('runtime', () => { it('default value', () => { - const warnHandler = jest.fn() + const warnHandler = vi.fn() const Foo = defineComponent({ props: buildProps({ diff --git a/packages/utils/package.json b/packages/utils/package.json index 0f3801b0b3..0ed948ce6a 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -2,6 +2,7 @@ "name": "@element-plus/utils", "private": true, "license": "MIT", + "main": "index.ts", "peerDependencies": { "vue": "^3.2.0" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 50fdd6d945..d5a8184e29 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -38,12 +38,14 @@ importers: '@typescript-eslint/parser': 5.12.0 '@vitejs/plugin-vue': 2.2.2 '@vitejs/plugin-vue-jsx': 1.3.7 + '@vitest/ui': ^0.3.2 '@vue/babel-plugin-jsx': 1.1.1 '@vue/test-utils': 2.0.0-rc.16 '@vue/tsconfig': 0.1.3 '@vueuse/core': ^7.6.0 async-validator: ^4.0.7 babel-jest: 26.6.3 + c8: ^7.11.0 chalk: 4.1.2 components-helper: 2.0.0 csstype: 2.6.19 @@ -84,6 +86,7 @@ importers: type-fest: 2.12.0 typescript: 4.5.5 unplugin-vue-define-options: 0.3.1 + vitest: ^0.3.2 vue: 3.2.30 vue-jest: 5.0.0-alpha.10 vue-router: 4.0.12 @@ -132,10 +135,12 @@ importers: '@typescript-eslint/parser': 5.12.0_eslint@8.9.0+typescript@4.5.5 '@vitejs/plugin-vue': 2.2.2_vue@3.2.30 '@vitejs/plugin-vue-jsx': 1.3.7 + '@vitest/ui': 0.3.2 '@vue/babel-plugin-jsx': 1.1.1_@babel+core@7.17.5 '@vue/test-utils': 2.0.0-rc.16_vue@3.2.30 '@vue/tsconfig': 0.1.3_@types+node@17.0.16 babel-jest: 26.6.3_@babel+core@7.17.5 + c8: 7.11.0 chalk: 4.1.2 components-helper: 2.0.0 csstype: 2.6.19 @@ -170,6 +175,7 @@ importers: type-fest: 2.12.0 typescript: 4.5.5 unplugin-vue-define-options: 0.3.1_a2d0c1fa84d0bf84d5748cef41c57115 + vitest: 0.3.2_7eedc1c4db875d438e18b4f15a9092b1 vue: 3.2.30 vue-jest: 5.0.0-alpha.10_9f18a56dc640bc0fc3dd15c5d03f3517 vue-router: 4.0.12_vue@3.2.30 @@ -480,15 +486,6 @@ packages: - supports-color dev: true - /@babel/generator/7.17.0: - resolution: {integrity: sha512-I3Omiv6FGOC29dtlZhkfXO6pgkmukJSlT26QjVvS1DGZe/NzSVCPG41X0tS21oZkJYlovfj9qDWgKP+Cn4bXxw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.17.0 - jsesc: 2.5.2 - source-map: 0.5.7 - dev: true - /@babel/generator/7.17.3: resolution: {integrity: sha512-+R6Dctil/MgUsZsZAkYgK+ADNSZzJRRy0TvY65T71z/CR854xHQ1EweBYXdfT+HNeN7w0cSJJEzgxZMv40pxsg==} engines: {node: '>=6.9.0'} @@ -670,7 +667,7 @@ packages: '@babel/helper-environment-visitor': 7.16.7 '@babel/helper-member-expression-to-functions': 7.16.7 '@babel/helper-optimise-call-expression': 7.16.7 - '@babel/traverse': 7.17.0 + '@babel/traverse': 7.17.3 '@babel/types': 7.17.0 transitivePeerDependencies: - supports-color @@ -1640,24 +1637,6 @@ packages: '@babel/types': 7.17.0 dev: true - /@babel/traverse/7.17.0: - resolution: {integrity: sha512-fpFIXvqD6kC7c7PUNnZ0Z8cQXlarCLtCUpt2S1Dx7PjoRtCFffvOkHHSom+m5HIxMZn5bIBVb71lhabcmjEsqg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.16.7 - '@babel/generator': 7.17.0 - '@babel/helper-environment-visitor': 7.16.7 - '@babel/helper-function-name': 7.16.7 - '@babel/helper-hoist-variables': 7.16.7 - '@babel/helper-split-export-declaration': 7.16.7 - '@babel/parser': 7.17.0 - '@babel/types': 7.17.0 - debug: 4.3.3 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - dev: true - /@babel/traverse/7.17.3: resolution: {integrity: sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw==} engines: {node: '>=6.9.0'} @@ -2798,6 +2777,16 @@ packages: '@babel/types': 7.17.0 dev: true + /@types/chai-subset/1.3.3: + resolution: {integrity: sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==} + dependencies: + '@types/chai': 4.3.0 + dev: true + + /@types/chai/4.3.0: + resolution: {integrity: sha512-/ceqdqeRraGolFTcfoXNiqjyQhZzbINDngeoAq9GoHa8PPK1yNzTaxWjA6BFWp5Ua9JpXEMSS4s5i9tS0hOJtw==} + dev: true + /@types/clean-css/4.2.5: resolution: {integrity: sha512-NEzjkGGpbs9S9fgC4abuBvTpVwE3i+Acu9BBod3PUyjDVZcNsGx61b8r2PphR61QGPnn0JHVs5ey6/I4eTrkxw==} dependencies: @@ -3232,6 +3221,12 @@ packages: vue: 3.2.30 dev: true + /@vitest/ui/0.3.2: + resolution: {integrity: sha512-bW2AWmfBxUlz4Xc0lpY1tfMf1MzK3ZnkzN9ACtDTrrWOQ4yEALgKxJm8qDW71x8qllWlrJTbO0R4xUVI96oc/A==} + dependencies: + sirv: 2.0.2 + dev: true + /@volar/code-gen/0.31.4: resolution: {integrity: sha512-ngivMEbBNd19v+EHdLyCJoIGRaoD9J4P20ZgdCEGf2voztja59u3Tilpf9r9ENy/731nG7XncToYm4+c1t/LhA==} dependencies: @@ -3304,7 +3299,7 @@ packages: '@babel/helper-module-imports': 7.16.7 '@babel/plugin-syntax-jsx': 7.16.7_@babel+core@7.17.5 '@babel/template': 7.16.7 - '@babel/traverse': 7.17.0 + '@babel/traverse': 7.17.3 '@babel/types': 7.17.0 '@vue/babel-helper-vue-transform-on': 1.0.2 camelcase: 6.2.0 @@ -4007,6 +4002,10 @@ packages: engines: {node: '>=0.8'} dev: true + /assertion-error/1.1.0: + resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} + dev: true + /assign-symbols/1.0.0: resolution: {integrity: sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=} engines: {node: '>=0.10.0'} @@ -4419,6 +4418,25 @@ packages: resolution: {integrity: sha1-y5T662HIaWRR2zZTThQi+U8K7og=} dev: true + /c8/7.11.0: + resolution: {integrity: sha512-XqPyj1uvlHMr+Y1IeRndC2X5P7iJzJlEJwBpCdBbq2JocXOgJfr+JVfJkyNMGROke5LfKrhSFXGFXnwnRJAUJw==} + engines: {node: '>=10.12.0'} + hasBin: true + dependencies: + '@bcoe/v8-coverage': 0.2.3 + '@istanbuljs/schema': 0.1.2 + find-up: 5.0.0 + foreground-child: 2.0.0 + istanbul-lib-coverage: 3.2.0 + istanbul-lib-report: 3.0.0 + istanbul-reports: 3.0.2 + rimraf: 3.0.2 + test-exclude: 6.0.0 + v8-to-istanbul: 8.1.1 + yargs: 16.2.0 + yargs-parser: 20.2.9 + dev: true + /cacache/15.2.0: resolution: {integrity: sha512-uKoJSHmnrqXgthDFx/IU6ED/5xd+NNGe+Bb+kLZy7Ku4P+BaiWEUflAKPZ7eAzsYGcsAGASJZsybXp+quEcHTw==} engines: {node: '>= 10'} @@ -4529,6 +4547,19 @@ packages: resolution: {integrity: sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=} dev: true + /chai/4.3.6: + resolution: {integrity: sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==} + engines: {node: '>=4'} + dependencies: + assertion-error: 1.1.0 + check-error: 1.0.2 + deep-eql: 3.0.1 + get-func-name: 2.0.0 + loupe: 2.3.4 + pathval: 1.1.1 + type-detect: 4.0.8 + dev: true + /chalk/2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} engines: {node: '>=4'} @@ -4569,6 +4600,10 @@ packages: resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} dev: true + /check-error/1.0.2: + resolution: {integrity: sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=} + dev: true + /check-more-types/2.24.0: resolution: {integrity: sha1-FCD/sQ/URNz8ebQ4kbv//TKoRgA=} engines: {node: '>= 0.8.0'} @@ -5297,6 +5332,13 @@ packages: resolution: {integrity: sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=} dev: true + /deep-eql/3.0.1: + resolution: {integrity: sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==} + engines: {node: '>=0.12'} + dependencies: + type-detect: 4.0.8 + dev: true + /deep-is/0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} dev: true @@ -6773,6 +6815,14 @@ packages: for-in: 1.0.2 dev: true + /foreground-child/2.0.0: + resolution: {integrity: sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==} + engines: {node: '>=8.0.0'} + dependencies: + cross-spawn: 7.0.3 + signal-exit: 3.0.5 + dev: true + /forever-agent/0.6.1: resolution: {integrity: sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=} dev: true @@ -6905,6 +6955,10 @@ packages: engines: {node: 6.* || 8.* || >= 10.*} dev: true + /get-func-name/2.0.0: + resolution: {integrity: sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=} + dev: true + /get-intrinsic/1.1.1: resolution: {integrity: sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==} dependencies: @@ -7999,6 +8053,11 @@ packages: engines: {node: '>=8'} dev: true + /istanbul-lib-coverage/3.2.0: + resolution: {integrity: sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==} + engines: {node: '>=8'} + dev: true + /istanbul-lib-instrument/4.0.3: resolution: {integrity: sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==} engines: {node: '>=8'} @@ -8015,7 +8074,7 @@ packages: resolution: {integrity: sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==} engines: {node: '>=8'} dependencies: - istanbul-lib-coverage: 3.0.0 + istanbul-lib-coverage: 3.2.0 make-dir: 3.1.0 supports-color: 7.2.0 dev: true @@ -8025,7 +8084,7 @@ packages: engines: {node: '>=8'} dependencies: debug: 4.3.3 - istanbul-lib-coverage: 3.0.0 + istanbul-lib-coverage: 3.2.0 source-map: 0.6.1 transitivePeerDependencies: - supports-color @@ -8943,6 +9002,12 @@ packages: engines: {node: '>=0.10.0'} dev: true + /loupe/2.3.4: + resolution: {integrity: sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==} + dependencies: + get-func-name: 2.0.0 + dev: true + /lru-cache/6.0.0: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} @@ -10034,6 +10099,10 @@ packages: engines: {node: '>=8'} dev: true + /pathval/1.1.1: + resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} + dev: true + /pend/1.2.0: resolution: {integrity: sha1-elfrVQpng/kRUzH89GY9XI4AelA=} dev: true @@ -11052,6 +11121,15 @@ packages: totalist: 2.0.0 dev: true + /sirv/2.0.2: + resolution: {integrity: sha512-4Qog6aE29nIjAOKe/wowFTxOdmbEZKb+3tsLljaBRzJwtqto0BChD2zzH0LhgCSXiI+V7X+Y45v14wBZQ1TK3w==} + engines: {node: '>= 10'} + dependencies: + '@polka/url': 1.0.0-next.20 + mrmime: 1.0.0 + totalist: 3.0.0 + dev: true + /sisteransi/1.0.5: resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} dev: true @@ -11651,6 +11729,16 @@ packages: engines: {node: '>=0.10.0'} dev: true + /tinypool/0.1.2: + resolution: {integrity: sha512-fvtYGXoui2RpeMILfkvGIgOVkzJEGediv8UJt7TxdAOY8pnvUkFg/fkvqTfXG9Acc9S17Cnn1S4osDc2164guA==} + engines: {node: '>=14.0.0'} + dev: true + + /tinyspy/0.2.10: + resolution: {integrity: sha512-Qij6rGWCDjWIejxCXXVi6bNgvrYBp3PbqC4cBP/0fD6WHDOHCw09Zd13CsxrDqSR5PFq01WeqDws8t5lz5sH0A==} + engines: {node: '>=14.0.0'} + dev: true + /tmp/0.0.33: resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} engines: {node: '>=0.6.0'} @@ -11730,6 +11818,11 @@ packages: engines: {node: '>=6'} dev: true + /totalist/3.0.0: + resolution: {integrity: sha512-eM+pCBxXO/njtF7vdFsHuqb+ElbxqtI4r5EAvk6grfAFyJ6IvWlSkfZ5T9ozC6xWw3Fj1fGoSmrl0gUs46JVIw==} + engines: {node: '>=6'} + dev: true + /tough-cookie/2.5.0: resolution: {integrity: sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==} engines: {node: '>=0.8'} @@ -12288,6 +12381,15 @@ packages: source-map: 0.7.3 dev: true + /v8-to-istanbul/8.1.1: + resolution: {integrity: sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==} + engines: {node: '>=10.12.0'} + dependencies: + '@types/istanbul-lib-coverage': 2.0.3 + convert-source-map: 1.8.0 + source-map: 0.7.3 + dev: true + /v8flags/3.2.0: resolution: {integrity: sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==} engines: {node: '>= 0.10'} @@ -12464,6 +12566,40 @@ packages: - stylus dev: true + /vitest/0.3.2_7eedc1c4db875d438e18b4f15a9092b1: + resolution: {integrity: sha512-Xc0u8BVPBdD029uDcLSYDvy1MFenC6V8WvTJOGdld6NNWgz/swgsMvwZNzftsDohmHLgDyck8A+TaQdDd1tNwA==} + engines: {node: '>=14.14.0'} + hasBin: true + peerDependencies: + '@vitest/ui': '*' + c8: '*' + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@vitest/ui': + optional: true + c8: + optional: true + happy-dom: + optional: true + jsdom: + optional: true + dependencies: + '@types/chai': 4.3.0 + '@types/chai-subset': 1.3.3 + '@vitest/ui': 0.3.2 + c8: 7.11.0 + chai: 4.3.6 + local-pkg: 0.4.1 + tinypool: 0.1.2 + tinyspy: 0.2.10 + vite: 2.8.3_sass@1.49.7 + transitivePeerDependencies: + - less + - sass + - stylus + dev: true + /void-elements/3.1.0: resolution: {integrity: sha1-YU9/v42AHwu18GYfWy9XhXUOTwk=} engines: {node: '>=0.10.0'} @@ -12949,6 +13085,19 @@ packages: yargs-parser: 18.1.3 dev: true + /yargs/16.2.0: + resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} + engines: {node: '>=10'} + dependencies: + cliui: 7.0.4 + escalade: 3.1.1 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 20.2.9 + dev: true + /yargs/17.2.1: resolution: {integrity: sha512-XfR8du6ua4K6uLGm5S6fA+FIJom/MdJcFNVY8geLlp2v8GYbOXD4EB1tPNZsRn4vBzKGMgb5DRZMeWuFc2GO8Q==} engines: {node: '>=12'} diff --git a/tsconfig.json b/tsconfig.json index 39669f74e5..9ef7663e23 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,13 +11,11 @@ "allowSyntheticDefaultImports": true, "types": ["unplugin-vue-define-options"] }, - "references": [{ "path": "./tsconfig.jest.json" }], + "references": [ + { "path": "./tsconfig.vite-config.json" }, + { "path": "./tsconfig.jest.json" }, + { "path": "./tsconfig.vitest.json" } + ], "include": ["packages", "typings"], - "exclude": [ - "node_modules", - "**/dist", - "**/__tests__", - "**/*.test.*", - "**/*.spec.*" - ] + "exclude": ["node_modules", "**/dist", "**/__tests__/**/*"] } diff --git a/tsconfig.vite-config.json b/tsconfig.vite-config.json new file mode 100644 index 0000000000..688f689a68 --- /dev/null +++ b/tsconfig.vite-config.json @@ -0,0 +1,8 @@ +{ + "extends": "@vue/tsconfig/tsconfig.node.json", + "include": ["vite.config.*", "vitest.config.*"], + "compilerOptions": { + "composite": true, + "types": ["node", "vitest"] + } +} diff --git a/tsconfig.vitest.json b/tsconfig.vitest.json new file mode 100644 index 0000000000..389104bb10 --- /dev/null +++ b/tsconfig.vitest.json @@ -0,0 +1,10 @@ +{ + "extends": "@vue/tsconfig/tsconfig.node.json", + "include": ["packages/**/*.vitest.*"], + "compilerOptions": { + "composite": true, + "lib": ["DOM"], + "types": ["node"], + "jsx": "preserve" + } +} diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 0000000000..abd606015d --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,13 @@ +import { defineConfig } from 'vite' +import Vue from '@vitejs/plugin-vue' +import VueJsx from '@vitejs/plugin-vue-jsx' +import DefineOptions from 'unplugin-vue-define-options/vite' + +export default defineConfig({ + plugins: [Vue(), VueJsx(), DefineOptions()], + test: { + include: ['**/*.vitest.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], + exclude: ['**/*.test.*', '**/*.spec.*'], + environment: 'jsdom', + }, +})