Skip to content

Commit aaf90d9

Browse files
authored
test: switch to vitest (element-plus#5991)
* test: use vitest * test: add script and ci * chore: improve tsconfig * refactor: use-form-item * fix: remove unused * chore: improve scripts * test: improve mock * refactor: change coverage
1 parent 0b4acfb commit aaf90d9

30 files changed

+507
-348
lines changed

.github/workflows/unit-test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ jobs:
3232
- name: Lint
3333
run: pnpm lint
3434
- name: Test
35-
run: pnpm test -- --coverage
35+
run: pnpm test:coverage
3636
- name: Upload to codecov.io
3737
uses: codecov/codecov-action@v2
3838
with:

CONTRIBUTING.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ pnpm install
4040
Then you can following command to verify your installation.
4141

4242
```shell
43-
pnpm test
44-
pnpm run format
43+
pnpm t
44+
pnpm format
4545
```
4646

4747
## Getting Started developing

jest.config.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@
33
*/
44
module.exports = {
55
setupFiles: ['./jest.setup.js'],
6+
testMatch: [
7+
'**/__tests__/**/*.[jt]s?(x)',
8+
'**/?(*.)+(spec|test).[jt]s?(x)',
9+
'!**/**vitest**',
10+
],
611
testPathIgnorePatterns: ['/node_modules/', 'dist'],
712
modulePathIgnorePatterns: ['/node_modules/', 'dist', 'cypress'],
813
testEnvironment: 'jsdom',

package.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@
1111
},
1212
"scripts": {
1313
"cz": "git-cz",
14-
"test": "jest",
14+
"test": "pnpm test:jest && pnpm test:vitest",
15+
"test:jest": "jest",
16+
"test:vitest": "vitest",
17+
"test:coverage": "vitest --coverage",
1518
"prepare:e2e": "if [ ! -d \"docs/.vitepress/dist\" ]; then pnpm run docs:build; fi;",
1619
"e2e": "cypress open",
1720
"e2e:ci": "cypress run",
@@ -96,10 +99,12 @@
9699
"@typescript-eslint/parser": "5.12.0",
97100
"@vitejs/plugin-vue": "2.2.2",
98101
"@vitejs/plugin-vue-jsx": "1.3.7",
102+
"@vitest/ui": "^0.3.2",
99103
"@vue/babel-plugin-jsx": "1.1.1",
100104
"@vue/test-utils": "2.0.0-rc.16",
101105
"@vue/tsconfig": "0.1.3",
102106
"babel-jest": "26.6.3",
107+
"c8": "^7.11.0",
103108
"chalk": "4.1.2",
104109
"components-helper": "2.0.0",
105110
"csstype": "2.6.19",
@@ -134,6 +139,7 @@
134139
"type-fest": "2.12.0",
135140
"typescript": "4.5.5",
136141
"unplugin-vue-define-options": "0.3.1",
142+
"vitest": "^0.3.2",
137143
"vue": "3.2.30",
138144
"vue-jest": "5.0.0-alpha.10",
139145
"vue-router": "4.0.12",

packages/constants/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"name": "@element-plus/constants",
33
"private": true,
4-
"license": "MIT"
4+
"license": "MIT",
5+
"main": "index.ts"
56
}

packages/hooks/__tests__/use-attrs.spec.ts renamed to packages/hooks/__tests__/use-attrs.vitest.tsx

Lines changed: 30 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,58 @@
1+
import { defineComponent } from 'vue'
12
import { mount } from '@vue/test-utils'
3+
import { describe, it, expect, fn, afterEach, vi } from 'vitest'
24
import { useAttrs } from '../use-attrs'
3-
import type { ComponentOptions } from 'vue'
45

56
const CLASS = 'a'
67
const WIDTH = '50px'
78
const TEST_KEY = 'test'
89
const TEST_VALUE = 'fake'
910
const ANOTHER_TEST_VALUE = 'fake1'
1011

11-
const handleClick = jest.fn()
12+
const handleClick = fn()
1213

1314
const genComp = (
1415
inheritAttrs = true,
1516
excludeListeners = false,
1617
excludeKeys: string[] = []
1718
) => {
18-
return {
19-
template: `
20-
<div>
21-
<span v-bind="attrs"></span>
22-
</div>
23-
`,
19+
return defineComponent({
2420
inheritAttrs,
2521
props: {},
2622
setup() {
2723
const attrs = useAttrs({ excludeListeners, excludeKeys })
28-
29-
return {
30-
attrs,
31-
}
24+
return () => (
25+
<div>
26+
<span {...attrs.value} />
27+
</div>
28+
)
3229
},
33-
}
30+
})
3431
}
3532

36-
const _mount = (Comp: ComponentOptions) => {
33+
const _mount = (Comp: ReturnType<typeof genComp>) => {
3734
return mount({
38-
components: { Comp },
39-
template: `
40-
<comp
41-
class="${CLASS}"
42-
style="width: ${WIDTH}"
43-
${TEST_KEY}="${TEST_VALUE}"
44-
@click="handleClick"
45-
/>`,
46-
methods: {
47-
handleClick,
35+
setup() {
36+
return () => (
37+
<Comp
38+
class={CLASS}
39+
style={{ width: WIDTH }}
40+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
41+
// @ts-expect-error
42+
onClick={handleClick}
43+
{...{ [TEST_KEY]: TEST_VALUE }}
44+
/>
45+
)
4846
},
4947
})
5048
}
5149

52-
afterEach(() => {
53-
handleClick.mockClear()
54-
})
55-
5650
describe('useAttrs', () => {
57-
test('class and style should not bind to child node', async () => {
51+
afterEach(() => {
52+
vi.restoreAllMocks()
53+
})
54+
55+
it('class and style should not bind to child node', async () => {
5856
const wrapper = _mount(genComp())
5957
const container = wrapper.element as HTMLDivElement
6058
const span = wrapper.find('span')
@@ -70,15 +68,15 @@ describe('useAttrs', () => {
7068
expect(handleClick).toBeCalledTimes(2)
7169
})
7270

73-
test("child node's attributes should update when prop change", async () => {
71+
it("child node's attributes should update when prop change", async () => {
7472
const wrapper = _mount(genComp())
7573
const span = wrapper.find('span')
7674

7775
await wrapper.setProps({ [TEST_KEY]: ANOTHER_TEST_VALUE })
7876
expect(span.attributes(TEST_KEY)).toBe(ANOTHER_TEST_VALUE)
7977
})
8078

81-
test('excluded listeners should not bind to child node', async () => {
79+
it('excluded listeners should not bind to child node', async () => {
8280
const wrapper = _mount(genComp(true, true))
8381
const span = wrapper.find('span')
8482

@@ -87,7 +85,7 @@ describe('useAttrs', () => {
8785
expect(handleClick).toBeCalledTimes(1)
8886
})
8987

90-
test('excluded attributes should not bind to child node', async () => {
88+
it('excluded attributes should not bind to child node', async () => {
9189
const wrapper = _mount(genComp(true, false, [TEST_KEY]))
9290
const span = wrapper.find('span')
9391

packages/hooks/__tests__/use-deprecated.spec.ts renamed to packages/hooks/__tests__/use-deprecated.vitest.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
import { computed, defineComponent, nextTick } from 'vue'
22
import { mount } from '@vue/test-utils'
3+
import { describe, it, fn, vi, expect, afterEach } from 'vitest'
34
import { debugWarn } from '@element-plus/utils'
45
import { useDeprecated } from '../use-deprecated'
56

6-
jest.mock('@element-plus/utils/error', () => {
7+
const AXIOM = 'Rem is the best girl'
8+
9+
vi.mock('@element-plus/utils/error', async () => {
710
return {
8-
debugWarn: jest.fn(),
11+
...(await vi.importActual<any>('@element-plus/utils/error')),
12+
debugWarn: fn(),
913
}
1014
})
1115

@@ -24,14 +28,15 @@ const DummyComponent = defineComponent({
2428
},
2529
computed(() => props.shouldWarn)
2630
)
31+
return () => AXIOM
2732
},
28-
template: `<div>Rem is the best girl</div>`,
2933
})
3034

3135
describe('useDeprecated', () => {
32-
beforeEach(() => {
33-
;(debugWarn as jest.Mock).mockClear()
36+
afterEach(() => {
37+
vi.restoreAllMocks()
3438
})
39+
3540
it('should warn when condition is true', async () => {
3641
mount(DummyComponent, {
3742
props: {

packages/hooks/__tests__/use-focus.spec.ts renamed to packages/hooks/__tests__/use-focus.vitest.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { ref } from 'vue'
2+
import { describe, it, expect } from 'vitest'
23
import { useFocus } from '../use-focus'
34

45
describe('useFocus', () => {

packages/hooks/__tests__/use-form-item.spec.ts renamed to packages/hooks/__tests__/use-form-item.vitest.tsx

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import { h, provide } from 'vue'
1+
import { defineComponent, provide } from 'vue'
22
import { NOOP } from '@vue/shared'
33
import { mount } from '@vue/test-utils'
4+
import { describe, it, expect } from 'vitest'
45
import { ElButton } from '@element-plus/components'
56
import {
67
elFormKey,
@@ -16,23 +17,16 @@ import type {
1617

1718
const AXIOM = 'Rem is the best girl'
1819

19-
const Component = {
20-
render() {
21-
return h(ElButton, this.$attrs, {
22-
default: () => [AXIOM],
23-
})
24-
},
25-
}
26-
27-
const mountComponent = (setup = NOOP, options = {}) => {
28-
return mount(
29-
{
30-
...Component,
20+
const mountComponent = (setup = NOOP, options = {}) =>
21+
mount(
22+
defineComponent({
3123
setup,
32-
},
24+
render() {
25+
return <ElButton {...this.$attrs}>{AXIOM}</ElButton>
26+
},
27+
}),
3328
options
3429
)
35-
}
3630

3731
describe('use-form-item', () => {
3832
it('should return local value', () => {
@@ -44,14 +38,10 @@ describe('use-form-item', () => {
4438
const propSize = 'small'
4539
const wrapper = mountComponent(
4640
() => {
47-
provide(elFormItemKey, {
48-
size: 'large',
49-
} as ElFormItemContext)
41+
provide(elFormItemKey, { size: 'large' } as ElFormItemContext)
5042
},
5143
{
52-
props: {
53-
size: propSize,
54-
},
44+
props: { size: propSize },
5545
}
5646
)
5747

packages/hooks/__tests__/use-locale.spec.ts renamed to packages/hooks/__tests__/use-locale.vitest.tsx

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,43 @@
1-
import { h, nextTick, computed } from 'vue'
1+
import { nextTick, computed, defineComponent } from 'vue'
22
import { mount } from '@vue/test-utils'
3+
import { describe, it, expect, beforeEach, afterEach } from 'vitest'
34
import Chinese from '@element-plus/locale/lang/zh-cn'
45
import English from '@element-plus/locale/lang/en'
56
import { useLocale, buildTranslator } from '../use-locale'
67
import { provideGlobalConfig } from '..'
8+
import type { Language } from '@element-plus/locale'
9+
import type { PropType, ComponentPublicInstance } from 'vue'
10+
import type { VueWrapper } from '@vue/test-utils'
711

8-
const TestComp = {
12+
const TestComp = defineComponent({
913
setup() {
1014
const { t } = useLocale()
11-
return () => {
12-
return h(
13-
'div',
14-
{ class: 'locale-manifest' },
15-
t('el.popconfirm.confirmButtonText')
16-
)
17-
}
15+
return () => (
16+
<div class="locale-manifest">{t('el.popconfirm.confirmButtonText')}</div>
17+
)
1818
},
19-
}
19+
})
2020

2121
describe('use-locale', () => {
22-
let wrapper
22+
let wrapper: VueWrapper<ComponentPublicInstance>
23+
2324
beforeEach(() => {
2425
wrapper = mount(
2526
{
2627
props: {
27-
locale: Object,
28+
locale: Object as PropType<Language>,
2829
},
2930
components: {
3031
'el-test': TestComp,
3132
},
3233
setup(props, { slots }) {
3334
provideGlobalConfig(computed(() => ({ locale: props.locale })))
34-
return () => slots.default()
35+
return () => slots.default?.()
3536
},
3637
},
3738
{
38-
props: {
39-
locale: Chinese,
40-
},
41-
slots: {
42-
default: () => h(TestComp),
43-
},
39+
props: { locale: Chinese },
40+
slots: { default: () => <TestComp /> },
4441
}
4542
)
4643
})
@@ -70,7 +67,7 @@ describe('use-locale', () => {
7067
)
7168
})
7269

73-
test('return key name if not defined', () => {
70+
it('return key name if not defined', () => {
7471
const t = buildTranslator(English)
7572
expect(t('el.popconfirm.someThing')).toBe('el.popconfirm.someThing')
7673
})

0 commit comments

Comments
 (0)