Skip to content

Commit 9befd8b

Browse files
committed
Add unit tests.
1 parent 2ed47bc commit 9befd8b

14 files changed

+848
-2
lines changed

.babelrc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
22
"presets": [
3-
["@babel/preset-env", { "modules": false }]
3+
["@babel/preset-env"]
44
]
5-
}
5+
}

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
dev
22
node_modules
33
npm-debug.log
4+
coverage
45
demos/dev/
56
demos/dev*/
67
demos/**/*.map

jest.config.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
module.exports = {
2+
transformIgnorePatterns: [
3+
'node_modules'
4+
],
5+
collectCoverage: true,
6+
coverageReporters: [
7+
'html',
8+
'text-summary'
9+
],
10+
collectCoverageFrom: [
11+
'**/index.js',
12+
'!**/node_modules/**',
13+
'!**/test/**',
14+
],
15+
// testRegex: '/test/base.test.js?$'
16+
}

package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
"index.js"
88
],
99
"scripts": {
10+
"test": "jest",
1011
"lint": "eslint index.js",
12+
"ci": "npm run lint && npm run test",
1113
"dev": "npm run server & npm run demo:dev",
1214
"server": "node node_modules/@tangbc/tiny-node-server",
1315
"demo:dev": "cross-env NODE_ENV=development webpack --config ./demos/webpack.conf.js",
@@ -37,6 +39,8 @@
3739
"@babel/core": "^7.4.0",
3840
"@babel/preset-env": "^7.4.2",
3941
"@tangbc/tiny-node-server": "^1.0.4",
42+
"@vue/test-utils": "^1.0.0-beta.29",
43+
"babel-jest": "^24.7.0",
4044
"babel-loader": "^8.0.5",
4145
"babel-preset-env": "^1.7.0",
4246
"cross-env": "^5.2.0",
@@ -48,6 +52,7 @@
4852
"eslint-plugin-node": "^8.0.1",
4953
"eslint-plugin-promise": "^4.0.1",
5054
"eslint-plugin-standard": "^4.0.0",
55+
"jest": "^24.7.0",
5156
"less": "^3.9.0",
5257
"less-loader": "^4.1.0",
5358
"vue": "^2.6.10",

test/base.test.js

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import VirtualList from '../index'
2+
import { mount } from '@vue/test-utils'
3+
import { getIndexList } from './util'
4+
5+
// for testing base build.
6+
const theme = 'base-test'
7+
8+
describe(theme, () => {
9+
const listCount = 1000
10+
const wrapper = mount({
11+
template: `
12+
<div id="app" style="width: 300px;">
13+
<virtual-list class="list"
14+
:size="40"
15+
:remain="6"
16+
>
17+
<div class="for-item"
18+
v-for="(item, index) in items"
19+
:key="index"
20+
style="height: 40px; line-height: 40px;"
21+
>
22+
<span class="for-item-text">{{ item }}</span>
23+
</div>
24+
</virtual-list>
25+
</div>
26+
`,
27+
28+
name: 'test',
29+
30+
components: {
31+
'virtual-list': VirtualList
32+
},
33+
34+
data () {
35+
return {
36+
items: getIndexList(listCount)
37+
}
38+
}
39+
})
40+
41+
it(`[${theme}] check mount success.`, () => {
42+
expect(wrapper.name()).toBe('test')
43+
expect(wrapper.is('div')).toBe(true)
44+
expect(wrapper.isEmpty()).toBe(false)
45+
expect(wrapper.isVueInstance()).toBe(true)
46+
})
47+
48+
it(`[${theme}] check list build success.`, () => {
49+
expect(wrapper.find('.for-item').exists()).toBe(true)
50+
expect(wrapper.find('.for-item-text').exists()).toBe(true)
51+
52+
// list wraper height is remain * size.
53+
const expectOutsideHeight = 40 * 6
54+
const listEl = wrapper.find('.list').vm.$el
55+
expect(listEl.style.height).toBe(`${expectOutsideHeight}px`)
56+
57+
const listWraperEl = listEl.querySelector('div')
58+
const expectPaddingBottom = listCount * 40 - expectOutsideHeight * 2
59+
expect(listWraperEl.style['padding-top']).toBe('0px')
60+
expect(listWraperEl.style['padding-bottom']).toBe(`${expectPaddingBottom}px`)
61+
})
62+
63+
it(`[${theme}] check build item count correct.`, () => {
64+
const itemFrags = wrapper.findAll('.for-item')
65+
66+
// default real dom count is remain + default bench.
67+
expect(itemFrags.length).toBe(6 + 6)
68+
69+
// check every item render content.
70+
for (let i = 0; i < itemFrags.length; i++) {
71+
const item = itemFrags.at(i)
72+
expect(item.text()).toBe('#' + i)
73+
expect(item.classes('for-item')).toBe(true)
74+
}
75+
})
76+
})

test/element.test.js

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import VirtualList from '../index'
2+
import { mount } from '@vue/test-utils'
3+
import { getIndexList } from './util'
4+
5+
// for testing props: rtag, wtag wclass.
6+
const theme = 'element-test'
7+
8+
describe(theme, () => {
9+
const initSize = 40
10+
const initRemian = 6
11+
const listCount = 1000
12+
13+
const wrapper = mount({
14+
template: `
15+
<div id="app" style="width: 300px;">
16+
<virtual-list class="list"
17+
:size="size"
18+
:remain="remian"
19+
rtag="div"
20+
wtag="ul"
21+
wclass="conetnt-box"
22+
>
23+
<li class="for-item"
24+
v-for="(item, index) in items"
25+
:key="index"
26+
:style="itemStyle"
27+
>
28+
<span class="for-item-text">{{ item }}</span>
29+
</li>
30+
</virtual-list>
31+
</div>
32+
`,
33+
34+
name: 'test',
35+
36+
components: {
37+
'virtual-list': VirtualList
38+
},
39+
40+
data () {
41+
return {
42+
size: initSize,
43+
remian: initRemian,
44+
items: getIndexList(listCount)
45+
}
46+
},
47+
48+
computed: {
49+
itemStyle () {
50+
return {
51+
'height': this.size + 'px',
52+
'line-height': this.size + 'px'
53+
}
54+
}
55+
}
56+
})
57+
58+
it(`[${theme}] check element tag and classname.`, () => {
59+
const listEl = wrapper.find('.list').vm.$el
60+
const listWraperEl = listEl.firstElementChild
61+
62+
expect(listEl.tagName).toBe('DIV')
63+
expect(listWraperEl.tagName).toBe('UL')
64+
expect(listWraperEl.className).toBe('conetnt-box')
65+
})
66+
})

test/event.test.js

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import VirtualList from '../index'
2+
import { mount } from '@vue/test-utils'
3+
import { getIndexList } from './util'
4+
import jest from 'jest-mock'
5+
6+
// for testing props: totop, tobottom and onscroll.
7+
const theme = 'event-test'
8+
9+
const mockReachTopCallback = jest.fn(() => {})
10+
const mockReachBottomCallback = jest.fn(() => {})
11+
const mockScrollCallback = jest.fn(() => {})
12+
13+
describe(theme, () => {
14+
const initSize = 40
15+
const initRemian = 6
16+
const listCount = 100
17+
18+
const wrapper = mount({
19+
template: `
20+
<div id="app" style="width: 300px;">
21+
<virtual-list class="list"
22+
:size="size"
23+
:remain="remian"
24+
:totop="onReachTop"
25+
:tobottom="onReachBottom"
26+
:onscroll="onScroll"
27+
>
28+
<div class="for-item"
29+
v-for="(item, index) in items"
30+
:key="index"
31+
:style="itemStyle"
32+
>
33+
<span class="for-item-text">{{ item }}</span>
34+
</div>
35+
</virtual-list>
36+
</div>
37+
`,
38+
39+
name: 'test',
40+
41+
components: {
42+
'virtual-list': VirtualList
43+
},
44+
45+
data () {
46+
return {
47+
size: initSize,
48+
remian: initRemian,
49+
items: getIndexList(listCount)
50+
}
51+
},
52+
53+
methods: {
54+
onReachTop () {
55+
mockReachTopCallback()
56+
},
57+
58+
onReachBottom () {
59+
mockReachBottomCallback()
60+
},
61+
62+
onScroll (e, info) {
63+
mockScrollCallback(e, info)
64+
}
65+
},
66+
67+
computed: {
68+
itemStyle () {
69+
return {
70+
'height': this.size + 'px',
71+
'line-height': this.size + 'px'
72+
}
73+
}
74+
}
75+
})
76+
77+
it(`[${theme}] check event fire and call params.`, () => {
78+
const list = wrapper.find('.list')
79+
const listEl = list.vm.$el
80+
81+
expect(mockReachTopCallback.mock.calls.length).toBe(0)
82+
expect(mockReachBottomCallback.mock.calls.length).toBe(0)
83+
expect(mockScrollCallback.mock.calls.length).toBe(0)
84+
85+
listEl.scrollTop = 100
86+
list.trigger('scroll')
87+
const callArgs = mockScrollCallback.mock.calls[0]
88+
expect(callArgs[0] instanceof Event).toBe(true)
89+
expect(Object.keys(callArgs[1])).toEqual(['offset', 'offsetAll', 'start', 'end'])
90+
expect(mockReachTopCallback.mock.calls.length).toBe(0)
91+
expect(mockReachBottomCallback.mock.calls.length).toBe(0)
92+
expect(mockScrollCallback.mock.calls.length).toBe(1)
93+
94+
listEl.scrollTop = 0
95+
list.trigger('scroll')
96+
expect(mockReachTopCallback.mock.calls.length).toBe(1)
97+
expect(mockReachBottomCallback.mock.calls.length).toBe(0)
98+
expect(mockScrollCallback.mock.calls.length).toBe(2)
99+
100+
listEl.scrollTop = listCount * initSize
101+
list.trigger('scroll')
102+
expect(mockReachTopCallback.mock.calls.length).toBe(1)
103+
expect(mockReachBottomCallback.mock.calls.length).toBe(1)
104+
expect(mockScrollCallback.mock.calls.length).toBe(3)
105+
})
106+
})

test/pos.conflict.test.js

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import VirtualList from '../index'
2+
import { mount } from '@vue/test-utils'
3+
import { getIndexList } from './util'
4+
5+
// for testing props: start and offset conflict.
6+
const theme = 'position-conflict-test'
7+
8+
describe(theme, () => {
9+
const initSize = 40
10+
const initRemian = 6
11+
const initStart = 30
12+
const initOffset = 5678
13+
const listCount = 1000
14+
15+
const wrapper = mount({
16+
template: `
17+
<div id="app" style="width: 300px;">
18+
<virtual-list class="list"
19+
:size="size"
20+
:remain="remian"
21+
:offset="offset"
22+
:start="start"
23+
>
24+
<div class="for-item"
25+
v-for="(item, index) in items"
26+
:key="index"
27+
:style="itemStyle"
28+
>
29+
<span class="for-item-text">{{ item }}</span>
30+
</div>
31+
</virtual-list>
32+
</div>
33+
`,
34+
35+
name: 'test',
36+
37+
components: {
38+
'virtual-list': VirtualList
39+
},
40+
41+
data () {
42+
return {
43+
size: initSize,
44+
remian: initRemian,
45+
offset: initOffset,
46+
start: initStart,
47+
items: getIndexList(listCount)
48+
}
49+
},
50+
51+
computed: {
52+
itemStyle () {
53+
return {
54+
'height': this.size + 'px',
55+
'line-height': this.size + 'px'
56+
}
57+
}
58+
}
59+
})
60+
61+
it(`[${theme}] check conflict.`, () => {
62+
const listEl = wrapper.find('.list').vm.$el
63+
const listWraperEl = listEl.querySelector('div')
64+
65+
const expectOutsideHeight = `${initRemian * initSize}px`
66+
expect(listEl.style.height).toBe(expectOutsideHeight)
67+
68+
// offset will not work.
69+
expect(listEl.scrollTop === initOffset).toBe(false)
70+
71+
// start works well.
72+
const expectPaddingTop = initStart * initSize
73+
expect(listWraperEl.style['padding-top']).toBe(`${expectPaddingTop}px`)
74+
})
75+
})

0 commit comments

Comments
 (0)