Skip to content

Commit 728a4ec

Browse files
committed
test: setup unit tests suite using Jest
1 parent f5729b1 commit 728a4ec

File tree

8 files changed

+2364
-85
lines changed

8 files changed

+2364
-85
lines changed

Diff for: .babelrc

-12
This file was deleted.

Diff for: babel.config.js

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
module.exports = {
2+
presets: [
3+
[
4+
'@babel/preset-env',
5+
{
6+
// Jest tests are run in Node and it requires commonjs modules
7+
modules: process.env.NODE_ENV === 'test' ? 'commonjs' : false,
8+
loose: true
9+
}
10+
]
11+
],
12+
plugins: ['@vue/babel-plugin-jsx']
13+
}

Diff for: jest.config.js

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
transform: {
3+
'\\.[jt]sx?$': 'babel-jest'
4+
}
5+
}

Diff for: package.json

+7-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
"sideEffects": false,
1818
"scripts": {
1919
"prepublishOnly": "npm run build",
20-
"test": "echo fine",
20+
"test": "jest",
21+
"test:dev": "jest --watch",
2122
"build": "bili",
2223
"storybook": "poi -so --config stories/poi.config.js",
2324
"build:storybook": "poi --prod --config stories/poi.config.js"
@@ -28,10 +29,15 @@
2829
},
2930
"license": "MIT",
3031
"devDependencies": {
32+
"@babel/core": "^7.12.10",
33+
"@babel/preset-env": "^7.12.11",
3134
"@types/poi": "^12.5.0",
3235
"@vue/babel-plugin-jsx": "^1.0.2",
3336
"@vue/compiler-sfc": "^3.0.5",
37+
"@vue/test-utils": "^2.0.0-beta.14",
38+
"babel-jest": "^26.6.3",
3439
"bili": "^5.0.5",
40+
"jest": "^26.6.3",
3541
"poi": "12.10.3",
3642
"vue": "^3.0.5",
3743
"vue-loader": "^16.1.2",

Diff for: src/ContentLoader.spec.js

+198
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
import { mount } from '@vue/test-utils'
2+
import ContentLoader from './ContentLoader'
3+
4+
describe('ContentLoader', () => {
5+
it('has default values for props', () => {
6+
const wrapper = mount(ContentLoader)
7+
8+
expect(wrapper.vm.width).toBe(400)
9+
expect(wrapper.vm.height).toBe(130)
10+
expect(wrapper.vm.speed).toBe(2)
11+
expect(wrapper.vm.preserveAspectRatio).toBe('xMidYMid meet')
12+
expect(wrapper.vm.baseUrl).toBe('')
13+
expect(wrapper.vm.primaryColor).toBe('#f9f9f9')
14+
expect(wrapper.vm.secondaryColor).toBe('#ecebeb')
15+
expect(wrapper.vm.primaryOpacity).toBe(1)
16+
expect(wrapper.vm.secondaryOpacity).toBe(1)
17+
expect(wrapper.vm.animate).toBe(true)
18+
})
19+
20+
it('has viewbox, version and aspect ratio attributes on svg element', () => {
21+
const wrapper = mount(ContentLoader, {
22+
props: {
23+
width: 300,
24+
height: 200,
25+
preserveAspectRatio: 'xMaxYMid slice'
26+
}
27+
})
28+
29+
expect(wrapper.find('svg').attributes()).toEqual({
30+
preserveAspectRatio: 'xMaxYMid slice',
31+
version: '1.1',
32+
viewBox: '0 0 300 200'
33+
})
34+
})
35+
36+
it('has viewbox, version and aspect ratio attributes on svg element', () => {
37+
const wrapper = mount(ContentLoader, {
38+
props: {
39+
width: 300,
40+
height: 200,
41+
preserveAspectRatio: 'xMaxYMid slice'
42+
}
43+
})
44+
45+
expect(wrapper.find('svg').attributes()).toEqual({
46+
preserveAspectRatio: 'xMaxYMid slice',
47+
version: '1.1',
48+
viewBox: '0 0 300 200'
49+
})
50+
})
51+
52+
it('draws a rect filled by the gradient and clipped by the shapes', () => {
53+
const wrapper = mount(ContentLoader)
54+
55+
expect(wrapper.find('rect').attributes()).toEqual({
56+
style: `fill: url(#${wrapper.vm.idGradient});`,
57+
'clip-path': `url(#${wrapper.vm.idClip})`,
58+
x: '0',
59+
y: '0',
60+
width: '400',
61+
height: '130'
62+
})
63+
})
64+
65+
it('draws a clipPath with a unique ID', () => {
66+
const wrapper = mount(ContentLoader)
67+
68+
expect(wrapper.find('defs clipPath').attributes()).toEqual({
69+
id: wrapper.vm.idClip
70+
})
71+
})
72+
73+
it('draws a linear gradient with a unique ID', () => {
74+
const wrapper = mount(ContentLoader)
75+
76+
expect(wrapper.find('defs linearGradient').attributes()).toEqual({
77+
id: wrapper.vm.idGradient
78+
})
79+
})
80+
81+
it('draws a linear gradient with 3 stops', () => {
82+
const wrapper = mount(ContentLoader)
83+
const stops = wrapper.findAll('defs linearGradient stop')
84+
85+
expect(stops.length).toBe(3)
86+
expect(stops[0].attributes()).toEqual({
87+
offset: '0%',
88+
'stop-color': '#f9f9f9',
89+
'stop-opacity': '1'
90+
})
91+
expect(stops[1].attributes()).toEqual({
92+
offset: '50%',
93+
'stop-color': '#ecebeb',
94+
'stop-opacity': '1'
95+
})
96+
expect(stops[2].attributes()).toEqual({
97+
offset: '100%',
98+
'stop-color': '#f9f9f9',
99+
'stop-opacity': '1'
100+
})
101+
})
102+
103+
it('animates the gradient by default using given speed', () => {
104+
const wrapper = mount(ContentLoader)
105+
const animations = wrapper.findAll('defs linearGradient animate')
106+
107+
expect(animations.length).toBe(3)
108+
expect(animations[0].attributes()).toEqual({
109+
attributeName: 'offset',
110+
values: '-2; 1',
111+
dur: '2s',
112+
repeatCount: 'indefinite'
113+
})
114+
expect(animations[1].attributes()).toEqual({
115+
attributeName: 'offset',
116+
values: '-1.5; 1.5',
117+
dur: '2s',
118+
repeatCount: 'indefinite'
119+
})
120+
expect(animations[2].attributes()).toEqual({
121+
attributeName: 'offset',
122+
values: '-1; 2',
123+
dur: '2s',
124+
repeatCount: 'indefinite'
125+
})
126+
})
127+
128+
it('does not animate if animate prop is false', () => {
129+
const wrapper = mount(ContentLoader, {
130+
props: {
131+
animate: false
132+
}
133+
})
134+
135+
expect(wrapper.findAll('defs linearGradient animate').length).toBe(0)
136+
})
137+
138+
it('has a default element to clip with', () => {
139+
const wrapper = mount(ContentLoader)
140+
141+
expect(wrapper.find('defs clipPath rect').attributes()).toEqual({
142+
x: '0',
143+
y: '0',
144+
rx: '5',
145+
ry: '5',
146+
width: '400',
147+
height: '130'
148+
})
149+
})
150+
151+
it('outputs the default slot within the clipPath', () => {
152+
const wrapper = mount(ContentLoader, {
153+
slots: {
154+
default: '<circle cx="30" cy="30" r="30" />'
155+
}
156+
})
157+
158+
expect(wrapper.find('defs clipPath circle').html()).toEqual(
159+
'<circle cx="30" cy="30" r="30"></circle>'
160+
)
161+
})
162+
163+
it('use the baseUrl to link the gradient & clip path', () => {
164+
const wrapper = mount(ContentLoader, {
165+
props: {
166+
baseUrl: '/path'
167+
}
168+
})
169+
170+
expect(wrapper.find('rect').attributes()).toMatchObject({
171+
style: `fill: url(/path#${wrapper.vm.idGradient});`,
172+
'clip-path': `url(/path#${wrapper.vm.idClip})`
173+
})
174+
})
175+
176+
it('use the uniqueKey to generate static IDs', () => {
177+
const wrapper = mount(ContentLoader, {
178+
props: {
179+
uniqueKey: 'unique'
180+
}
181+
})
182+
183+
expect(wrapper.vm.idClip).toEqual('unique-idClip')
184+
expect(wrapper.vm.idGradient).toEqual('unique-idGradient')
185+
})
186+
187+
it('apply extra attributes on the root element', () => {
188+
const wrapper = mount(ContentLoader, {
189+
props: {
190+
class: 'loader',
191+
id: 'loader'
192+
}
193+
})
194+
195+
expect(wrapper.find('svg').classes()).toEqual(['loader'])
196+
expect(wrapper.find('svg').attributes()).toMatchObject({ id: 'loader' })
197+
})
198+
})

Diff for: src/__snapshots__/index.spec.js.snap

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`BulletListLoader renders its shapes 1`] = `
4+
Array [
5+
"<circle cx=\\"10\\" cy=\\"20\\" r=\\"8\\"></circle>",
6+
"<rect x=\\"25\\" y=\\"15\\" rx=\\"5\\" ry=\\"5\\" width=\\"220\\" height=\\"10\\"></rect>",
7+
"<circle cx=\\"10\\" cy=\\"50\\" r=\\"8\\"></circle>",
8+
"<rect x=\\"25\\" y=\\"45\\" rx=\\"5\\" ry=\\"5\\" width=\\"220\\" height=\\"10\\"></rect>",
9+
"<circle cx=\\"10\\" cy=\\"80\\" r=\\"8\\"></circle>",
10+
"<rect x=\\"25\\" y=\\"75\\" rx=\\"5\\" ry=\\"5\\" width=\\"220\\" height=\\"10\\"></rect>",
11+
"<circle cx=\\"10\\" cy=\\"110\\" r=\\"8\\"></circle>",
12+
"<rect x=\\"25\\" y=\\"105\\" rx=\\"5\\" ry=\\"5\\" width=\\"220\\" height=\\"10\\"></rect>",
13+
]
14+
`;
15+
16+
exports[`CodeLoader renders its shapes 1`] = `
17+
Array [
18+
"<rect x=\\"0\\" y=\\"0\\" rx=\\"3\\" ry=\\"3\\" width=\\"70\\" height=\\"10\\"></rect>",
19+
"<rect x=\\"80\\" y=\\"0\\" rx=\\"3\\" ry=\\"3\\" width=\\"100\\" height=\\"10\\"></rect>",
20+
"<rect x=\\"190\\" y=\\"0\\" rx=\\"3\\" ry=\\"3\\" width=\\"10\\" height=\\"10\\"></rect>",
21+
"<rect x=\\"15\\" y=\\"20\\" rx=\\"3\\" ry=\\"3\\" width=\\"130\\" height=\\"10\\"></rect>",
22+
"<rect x=\\"155\\" y=\\"20\\" rx=\\"3\\" ry=\\"3\\" width=\\"130\\" height=\\"10\\"></rect>",
23+
"<rect x=\\"15\\" y=\\"40\\" rx=\\"3\\" ry=\\"3\\" width=\\"90\\" height=\\"10\\"></rect>",
24+
"<rect x=\\"115\\" y=\\"40\\" rx=\\"3\\" ry=\\"3\\" width=\\"60\\" height=\\"10\\"></rect>",
25+
"<rect x=\\"185\\" y=\\"40\\" rx=\\"3\\" ry=\\"3\\" width=\\"60\\" height=\\"10\\"></rect>",
26+
"<rect x=\\"0\\" y=\\"60\\" rx=\\"3\\" ry=\\"3\\" width=\\"30\\" height=\\"10\\"></rect>",
27+
]
28+
`;
29+
30+
exports[`FacebookLoader renders its shapes 1`] = `
31+
Array [
32+
"<rect x=\\"70\\" y=\\"15\\" rx=\\"4\\" ry=\\"4\\" width=\\"117\\" height=\\"6.4\\"></rect>",
33+
"<rect x=\\"70\\" y=\\"35\\" rx=\\"3\\" ry=\\"3\\" width=\\"85\\" height=\\"6.4\\"></rect>",
34+
"<rect x=\\"0\\" y=\\"80\\" rx=\\"3\\" ry=\\"3\\" width=\\"350\\" height=\\"6.4\\"></rect>",
35+
"<rect x=\\"0\\" y=\\"100\\" rx=\\"3\\" ry=\\"3\\" width=\\"380\\" height=\\"6.4\\"></rect>",
36+
"<rect x=\\"0\\" y=\\"120\\" rx=\\"3\\" ry=\\"3\\" width=\\"201\\" height=\\"6.4\\"></rect>",
37+
"<circle cx=\\"30\\" cy=\\"30\\" r=\\"30\\"></circle>",
38+
]
39+
`;
40+
41+
exports[`InstagramLoader renders its shapes 1`] = `
42+
Array [
43+
"<circle cx=\\"30\\" cy=\\"30\\" r=\\"30\\"></circle>",
44+
"<rect x=\\"75\\" y=\\"13\\" rx=\\"4\\" ry=\\"4\\" width=\\"100\\" height=\\"13\\"></rect>",
45+
"<rect x=\\"75\\" y=\\"37\\" rx=\\"4\\" ry=\\"4\\" width=\\"50\\" height=\\"8\\"></rect>",
46+
"<rect x=\\"0\\" y=\\"70\\" rx=\\"5\\" ry=\\"5\\" width=\\"400\\" height=\\"400\\"></rect>",
47+
]
48+
`;
49+
50+
exports[`ListLoader renders its shapes 1`] = `
51+
Array [
52+
"<rect x=\\"0\\" y=\\"0\\" rx=\\"3\\" ry=\\"3\\" width=\\"250\\" height=\\"10\\"></rect>",
53+
"<rect x=\\"20\\" y=\\"20\\" rx=\\"3\\" ry=\\"3\\" width=\\"220\\" height=\\"10\\"></rect>",
54+
"<rect x=\\"20\\" y=\\"40\\" rx=\\"3\\" ry=\\"3\\" width=\\"170\\" height=\\"10\\"></rect>",
55+
"<rect x=\\"0\\" y=\\"60\\" rx=\\"3\\" ry=\\"3\\" width=\\"250\\" height=\\"10\\"></rect>",
56+
"<rect x=\\"20\\" y=\\"80\\" rx=\\"3\\" ry=\\"3\\" width=\\"200\\" height=\\"10\\"></rect>",
57+
"<rect x=\\"20\\" y=\\"100\\" rx=\\"3\\" ry=\\"3\\" width=\\"80\\" height=\\"10\\"></rect>",
58+
]
59+
`;

Diff for: src/index.spec.js

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { mount } from '@vue/test-utils'
2+
3+
import BulletListLoader from './BulletListLoader'
4+
import CodeLoader from './CodeLoader'
5+
import FacebookLoader from './FacebookLoader'
6+
import ListLoader from './ListLoader'
7+
import InstagramLoader from './InstagramLoader'
8+
9+
describe.each([
10+
['BulletListLoader', BulletListLoader],
11+
['CodeLoader', CodeLoader],
12+
['FacebookLoader', FacebookLoader],
13+
['ListLoader', ListLoader],
14+
['InstagramLoader', InstagramLoader]
15+
])('%s', (name, component) => {
16+
it('renders its shapes', () => {
17+
const wrapper = mount(component)
18+
19+
expect(wrapper.findAll('clipPath > *').map(c => c.html())).toMatchSnapshot()
20+
})
21+
22+
it('forwards attributes to ContentLoader', () => {
23+
const wrapper = mount(component, {
24+
props: {
25+
id: 'loader',
26+
class: 'loader'
27+
}
28+
})
29+
30+
expect(wrapper.attributes()).toMatchObject({
31+
id: 'loader',
32+
class: 'loader'
33+
})
34+
})
35+
})

0 commit comments

Comments
 (0)