Skip to content

Commit cf5eb98

Browse files
committed
test: added unit test about parser-compiler-sfc
1 parent ea30337 commit cf5eb98

File tree

3 files changed

+271
-11
lines changed

3 files changed

+271
-11
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
2+
import { beforeEach, describe, expect, test } from 'vitest'
3+
import { parse } from '@babel/parser'
4+
import {
5+
getVar,
6+
parseHasCSSVars,
7+
parseSetupBody,
8+
parseUseCSSVars,
9+
parserCompiledSfc,
10+
reSetVar,
11+
setVar,
12+
} from '../parser-compiled-sfc'
13+
import type { ImportSpecifier } from '@babel/types'
14+
describe('parseSetupBody', () => {
15+
let node: any
16+
17+
beforeEach(() => {
18+
node = {}
19+
reSetVar()
20+
})
21+
22+
test('should set isSetupEnter to true when node is an Identifier with name "setup"', () => {
23+
node.type = 'Identifier'
24+
node.name = 'setup'
25+
26+
parseSetupBody(node)
27+
28+
expect(getVar().isSetupEnter).toBe(true)
29+
})
30+
31+
test('should set setupBodyNode to node when isSetupEnter is true and node is a BlockStatement', () => {
32+
setVar('isSetupEnter', true)
33+
node.type = 'BlockStatement'
34+
35+
parseSetupBody(node)
36+
37+
expect(getVar().isSetupEnter).toBe(false)
38+
expect(getVar().setupBodyNode).toBe(node)
39+
})
40+
41+
test('should do nothing when node is not an Identifier with name "setup" and isSetupEnter is false', () => {
42+
node.type = 'BlockStatement'
43+
44+
parseSetupBody(node)
45+
46+
expect(getVar().isSetupEnter).toBe(false)
47+
expect(getVar().setupBodyNode).toEqual({})
48+
})
49+
50+
test('should do nothing when node is not a BlockStatement and isSetupEnter is true', () => {
51+
setVar('isSetupEnter', true)
52+
node.type = 'Identifier'
53+
node.name = 'not-setup'
54+
55+
parseSetupBody(node)
56+
57+
expect(getVar().isSetupEnter).toBe(true)
58+
expect(getVar().setupBodyNode).toEqual({})
59+
})
60+
})
61+
62+
describe('parseHasCSSVars', () => {
63+
beforeEach(() => {
64+
// reset the state of `hasCSSVars` to `false` after each test
65+
reSetVar()
66+
})
67+
68+
test('should set `hasCSSVars` to `true` if node type is Identifier with name "useCssVars" and has a parent ImportSpecifier', () => {
69+
const code = 'import { useCssVars } from \'vue\''
70+
const ast = parse(code, { sourceType: 'module' })
71+
72+
// the node representing the `useCssVars` identifier
73+
const node = (ast.program.body[0] as any).specifiers[0].local
74+
const parent = (ast.program.body[0] as any).specifiers[0] as ImportSpecifier
75+
76+
parseHasCSSVars(node, parent)
77+
78+
expect(getVar().hasCSSVars).toBe(true)
79+
})
80+
81+
test('should not set `hasCSSVars` to `true` if node type is not Identifier with name "useCssVars"', () => {
82+
const code = 'const a = 1'
83+
const ast = parse(code)
84+
85+
const node = ast.program.body[0].declarations[0].init
86+
87+
parseHasCSSVars(node, null!)
88+
89+
expect(getVar().hasCSSVars).toBe(false)
90+
})
91+
92+
test('should not set `hasCSSVars` to `true` if node has no parent ImportSpecifier', () => {
93+
const code = 'import useCssVars from \'vue\''
94+
const ast = parse(code, { sourceType: 'module' })
95+
96+
const node = (ast.program.body[0] as any).specifiers[0].local
97+
98+
parseHasCSSVars(node, null!)
99+
100+
expect(getVar().hasCSSVars).toBe(false)
101+
})
102+
})
103+
104+
describe('parseUseCSSVars function', () => {
105+
let node: Node & { scopeIds?: Set<string> }
106+
let parent: Node & { scopeIds?: Set<string> }
107+
108+
beforeEach(() => {
109+
reSetVar()
110+
node = {} as Node & { scopeIds?: Set<string> }
111+
parent = {} as Node & { scopeIds?: Set<string> }
112+
})
113+
114+
test('sets isUseCSSVarsEnter to true when called with _useCssVars identifier and a CallExpression parent', () => {
115+
node.type = 'Identifier';
116+
(node as any).name = '_useCssVars'
117+
parent.type = 'CallExpression'
118+
119+
parseUseCSSVars(node, parent as any)
120+
121+
expect(getVar().isUseCSSVarsEnter).toBe(true)
122+
})
123+
124+
test('does not set isUseCSSVarsEnter to true when called with non-_useCssVars identifier and a CallExpression parent', () => {
125+
node.type = 'Identifier';
126+
(node as any).name = 'foo'
127+
parent.type = 'CallExpression'
128+
129+
parseUseCSSVars(node, parent as any)
130+
131+
expect(getVar().isUseCSSVarsEnter).toBe(false)
132+
})
133+
134+
test('does not set isUseCSSVarsEnter to true when called with _useCssVars identifier and a non-CallExpression parent', () => {
135+
node.type = 'Identifier';
136+
(node as any).name = '_useCssVars'
137+
parent.type = 'Identifier'
138+
139+
parseUseCSSVars(node, parent as any)
140+
141+
expect(getVar().isUseCSSVarsEnter).toBe(false)
142+
})
143+
144+
test('does not set isUseCSSVarsEnter to true when called with _useCssVars identifier and no parent', () => {
145+
node.type = 'Identifier';
146+
(node as any).name = '_useCssVars'
147+
148+
parseUseCSSVars(node, undefined!)
149+
150+
expect(getVar().isUseCSSVarsEnter).toBe(false)
151+
})
152+
153+
test('sets useCSSVarsNode to the node when isUseCSSVarsEnter is true and node is an ObjectExpression', () => {
154+
setVar('isUseCSSVarsEnter', true)
155+
node.type = 'ObjectExpression'
156+
157+
parseUseCSSVars(node, parent as any)
158+
159+
expect(getVar().useCSSVarsNode).toBe(node)
160+
})
161+
162+
test('does not set useCSSVarsNode when isUseCSSVarsEnter is true and node is not an ObjectExpression', () => {
163+
setVar('isUseCSSVarsEnter', true)
164+
node.type = 'Identifier'
165+
166+
parseUseCSSVars(node, parent as any)
167+
168+
expect(getVar().useCSSVarsNode).not.toBe(node)
169+
})
170+
171+
test('does not set useCSSVarsNode when isUseCSSVarsEnter is false and node is an ObjectExpression', () => {
172+
setVar('isUseCSSVarsEnter', false)
173+
node.type = 'ObjectExpression'
174+
175+
parseUseCSSVars(node, parent as any)
176+
177+
expect(getVar().useCSSVarsNode).not.toBe(node)
178+
})
179+
})
180+
181+
describe('parserCompiledSfc', () => {
182+
test('should parse setupBodyNode when an Identifier named setup is encountered', () => {
183+
const code = `
184+
const comp = {
185+
setup() {
186+
console.log('Setting up...');
187+
}
188+
}
189+
`
190+
const res = parserCompiledSfc(code)
191+
expect(res.setupBodyNode.type).toBe('BlockStatement')
192+
})
193+
194+
test('should parse hasCSSVars when an Identifier named useCssVars is encountered with a parent ImportSpecifier', () => {
195+
const code = `
196+
import { useCssVars } from 'vue';
197+
useCssVars();
198+
`
199+
const res = parserCompiledSfc(code)
200+
expect(res.hasCSSVars).toBe(true)
201+
})
202+
203+
test('should parse useCSSVarsNode when an Identifier named _useCssVars is encountered with a parent CallExpression and an ObjectExpression node is encountered afterwards', () => {
204+
const code = `
205+
import {useCssVars as _useCssVars} from "vue"
206+
const comp = {
207+
setup() {
208+
_useCssVars((_ctx)=>({
209+
"1439c43b": color.value,
210+
211+
}));
212+
}
213+
}
214+
`
215+
const res = parserCompiledSfc(code)
216+
expect(res.useCSSVarsNode.type).toBe('ObjectExpression')
217+
})
218+
219+
test('should not parse setupBodyNode, hasCSSVars or useCSSVarsNode when there are no matches', () => {
220+
const code = `
221+
const a = 1;
222+
const b = 2;
223+
const c = a + b;
224+
`
225+
const res = parserCompiledSfc(code)
226+
expect(res.setupBodyNode).toEqual({})
227+
expect(res.hasCSSVars).toBe(false)
228+
expect(res.useCSSVarsNode).toEqual({})
229+
})
230+
})

packages/core/parser/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
export * from './parser-variable'
22
export * from './parser-import'
33
export * from './parser-vbindm'
4-
export * from './parser-compiled-sfc'
4+
export { parserCompiledSfc } from './parser-compiled-sfc'

packages/core/parser/parser-compiled-sfc.ts

+40-10
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ export interface IParseSFCRes {
1717

1818
let isSetupEnter = false
1919
let setupBodyNode = {} as BlockStatement
20-
// TODO: unit test
2120
export function parseSetupBody(node: Node & { scopeIds?: Set<string> }) {
2221
if ((node as Identifier).type === 'Identifier' && (node as Identifier).name === 'setup') {
2322
isSetupEnter = true
@@ -30,7 +29,6 @@ export function parseSetupBody(node: Node & { scopeIds?: Set<string> }) {
3029
}
3130

3231
let hasCSSVars = false
33-
// TODO: unit test
3432
export function parseHasCSSVars(
3533
node: Node & { scopeIds?: Set<string> },
3634
parent: ImportSpecifier) {
@@ -41,7 +39,7 @@ export function parseHasCSSVars(
4139
hasCSSVars = true
4240
}
4341

44-
let useCSSVarsNode = {} as ExpressionStatement
42+
let useCSSVarsNode = {} as ObjectExpression
4543
let isUseCSSVarsEnter = false
4644
export function parseUseCSSVars(
4745
node: Node & { scopeIds?: Set<string> },
@@ -54,18 +52,13 @@ export function parseUseCSSVars(
5452

5553
if (isUseCSSVarsEnter && (node as ObjectExpression).type === 'ObjectExpression') {
5654
isUseCSSVarsEnter = false
57-
useCSSVarsNode = node as ExpressionStatement
55+
useCSSVarsNode = node as ObjectExpression
5856
}
5957
}
6058

6159
// TODO: unit test
6260
export function parserCompiledSfc(code: string) {
63-
isSetupEnter = false
64-
setupBodyNode = {} as BlockStatement
65-
isUseCSSVarsEnter = false
66-
useCSSVarsNode = {} as ExpressionStatement
67-
hasCSSVars = false
68-
61+
reSetVar()
6962
const ast = babelParse(code, {
7063
sourceType: 'module',
7164
plugins: ['typescript'],
@@ -86,3 +79,40 @@ export function parserCompiledSfc(code: string) {
8679
useCSSVarsNode,
8780
} as IParseSFCRes
8881
}
82+
83+
export function reSetVar() {
84+
isSetupEnter = false
85+
setupBodyNode = {} as BlockStatement
86+
isUseCSSVarsEnter = false
87+
useCSSVarsNode = {} as ObjectExpression
88+
hasCSSVars = false
89+
}
90+
91+
// test only
92+
export function getVar() {
93+
return {
94+
isSetupEnter,
95+
setupBodyNode,
96+
isUseCSSVarsEnter,
97+
useCSSVarsNode,
98+
hasCSSVars,
99+
}
100+
}
101+
102+
// test only
103+
export function setVar(k, v) {
104+
if (k === 'isSetupEnter')
105+
isSetupEnter = v
106+
107+
if (k === 'setupBodyNode')
108+
setupBodyNode = v
109+
110+
if (k === 'isUseCSSVarsEnter')
111+
isUseCSSVarsEnter = v
112+
113+
if (k === 'useCSSVarsNode')
114+
useCSSVarsNode = v
115+
116+
if (k === 'hasCSSVars')
117+
hasCSSVars = v
118+
}

0 commit comments

Comments
 (0)